
;DEFINE( ROMVER,-1)		;REMOVE COMMENT TO MAKE ROM VERSION.

;DEFINE( BLOCKMODE,-1)		;REMOVE COMMENT FOR BLOCK MODE.  LEAVE FOR
				;STRIP MODE.
DEFINE( INDIRECT,-1)		;REMOVE COMMENT TO MAKE BLOCK MODE RUN
				;WITH 1 BYTE BLOCK NUMBER TABLES.
;DEFINE( SOLFILL,-1)		;REMOVE COMMENT TO MAKE AREAS OUTSIDE 
				;BACKGROUND BE SOLID.



.COMMAND -O			;ENABLE MULTIPLE OUTPUT FILES
.SEGMENT .MEMORY,H'8000		;DEFINE SEGMENT .MEMORY, LOAD AT 8000H
.MEMORY				;ACTIVATE SEGMENT .MEMORY

IFDEF( `BLOCKMODE', `
.ORG    32112   ;7D70H - JGT 01.25.90           (Was 7DA0H)
        ', ` 
.ORG    32176   ;7DB0H - JGT 01.25.90           (Was 7DE0H)
        ' )



		lda	DATA2		;high address.
		bmi	XUSERPG1	;It's in Code Page 0.

		lda	ALTBANK
		ldy	ALTINDX
		JSR	SELPAGE

XUSERPG1:
		jsr	USERPG2
		JMP	BACKFINISH

XUSERPG2:	
		lda	DATA2
		ora	#x'80		;Correct address just in case.
		pha
		lda	DATA1
		pha
		rts			;Call the USERSUB




	.DB	2,5,4,4,3,4,3,2,3,2,2,3,3,2,2,2		;CMD00
	.DB	2,1,1,1,1,4,3,1,1,1,2,4,3,3,2,5		;CMD10
	.DB	3,1,4,4,4,5,1,3,4,2,4,4,2,3,1,2		;CMD20
	.DB	2,9,2,1,1,6,5,4,4,6,3,3,5,3,3,2		;CMD30
	.DB	3,5,3,2,1,4,2,2,2,3,2,4,2,3,3,2		;CMD40
	.DB	3,4,4,5,3,2,2,3,4,3,2,3,2,2,2,4		;CMD50 
	.DB	4,5,4,3,2,3,4,6,1,5,2,3,3,5,7,6		;CMD60
	.DB	10,2,2,2,5,4,2,7,3,1,2,5,2,3,1,7	;CMD70
	.DB	3,3,5,3,2,2,2,2,2,3,2,3,1,2,2,1		;CMD80
 	.DB	3,3,4,4,4,1,3,2,2,1,3,3,2,2,5,5		;CMD90
 	.DB	5,2,1,5,2,1,3,1,1,3,2,3,1,1,4,2		;CMDA0
 	.DB	1,1,2,3,3,1,6,1,1,3,3,3,3,2,1,3		;CMDB0
	.DB	3,2,3,1,2				;CMDC0

	LDA	ENEMYPTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA			;SAVE IT
	BMI	XFCB15
	ORA	#128
	STA	ENEMYPTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XFCB15:	LDY	#0	
	CPX	#0
	BNE	XFCB17
	LDA	(ENEMYPTR),Y
	TAX			;GET THE COMMAND BYTE
	LDA	CMDLEN,X	;GET THE COUNT FOR THIS COMMAND
	TAX
XFCB17:	STX	SUBSVAR1	;RETURN THE COUNT BYTE
XFCB20:	LDA	(ENEMYPTR),Y
	STA	CMDBUF,Y	;FETCH LENGTH REQUESTED
	INY
	DEX
	BNE	XFCB20
	PLA
	BMI	XFCB30
	STA	ENEMYPTR+1	;RESTORE ORIGINAL BANK SPECIFICATION
	LDA	BACKBANK
	LDY	BACKINDX
	JMP	SELPAGE
XFCB30:	RTS	

	TSX
	INX
	INX
	INX			;GET PLACE TO PUT THE DATA
	LDA	SUBSVAR2	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XFSK10
	ORA	#128
	STA	SUBSVAR2
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XFSK10:	LDY	#0	
XFSK20:	LDA	(SUBSVAR1),Y
	STA	256,X			
	INY
	INX
	DEC	SUBSVAR3
	BNE	XFSK20
	PLA
	BMI	XFSK25
	STA	SUBSVAR2
	JMP	BACKFINISH
XFSK25:	RTS	


	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XLDC15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XLDC15:	CLC
	LDY	#0
XLDC20:	LDA	(NMI_PTR),Y	;GET A BYTE
	STA	SCNBUF,X	;QUE IT UP
	INX
	LDA	NMI_PTR
	ADC	TMP_NMI2	;SKIP TO NEXT ROW IN DATA
	STA	NMI_PTR
	BCC	XLDC30
	INC	NMI_PTR+1
	CLC
XLDC30:	DEC	TMP_NMI1
	BNE	XLDC20

XLDC35:	PLA
	BMI	XLDC40
	LDA	NMI_PTR+1
	EOR	#128
	STA	NMI_PTR+1
	JMP	BACKFINISH
XLDC40:	RTS	


IFDEF( `BLOCKMODE', `		;BLOCK MODE HAS A Y STARTING OFFSET

	LDY	#0
	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XLPC14
	ORA	#128
	STA	NMI_PTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XLPC14:	LDY	#0
XLPC15:	LDA	(NMI_PTR),Y	;GET THE BYTE
	STA	TMP_NMI6,X	;QUE IT UP
	INX
	DEC	TMP_NMI1
	BEQ	XLDC35		;SHARE SOME ENDING CODE
	LDY	#2
	JMP	LPC15
	
	', `

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XLPC14
	ORA	#128
	STA	NMI_PTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XLPC14:	LDY	#0
XLPC15:	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI4
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI3
	STA	SCNBUF,X
	INX
	LDA	#1		;WE ALWAYS JUST QUE 1 IN THIS CASE
	STA	SCNBUF,X
	INX

	LDA	(NMI_PTR),Y	;GET THE BYTE
	STA	SCNBUF,X		;QUE IT UP
	INX
	TYA
	CLC
	ADC	TMP_NMI2	;UPDATE INDEX WITHIN OUR DATA
	TAY
	BCC	XLPC20
	INC	NMI_PTR+1


XLPC20:	LDA	TMP_NMI3
	CLC
	ADC	#8		;SKIP TO NEXT PALETTE ROW
	STA	TMP_NMI3

 	DEC	TMP_NMI1
 	BNE	XLPC15
	JMP	LDC35		;SHARE A HAPPY ENDING	

	' )


IFDEF( `BLOCKMODE', `		

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XLDR15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XLDR15:	CLC
	LDY	#0
XLDR20:	LDA	(NMI_PTR),Y	;GET A BYTE
	STA	SCNBUF,X	;QUE IT UP
	INX
	LDA	NMI_PTR
	ADC	#1		;SKIP TO NEXT COL IN DATA
	STA	NMI_PTR
	BCC	XLDR30
	INC	NMI_PTR+1
	CLC
XLDR30:	DEC	TMP_NMI1
	BNE	XLDR20
	JMP	LDC35

	', )


IFDEF( `BLOCKMODE', `		

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	XSHR15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
XSHR15:	LDY	#0
XSHR20:	LDA	(NMI_PTR),Y	;GET A BYTE
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	;SHIFT THE TOP NIBBLE INTO THE EXISTING BYTE
	INX
	LDA	NMI_PTR
	CLC
	ADC	#1		;SKIP TO NEXT COL IN DATA
	STA	NMI_PTR
	BCC	XSHR30
	INC	NMI_PTR+1
XSHR30:	DEC	TMP_NMI1
	BNE	XSHR20
	JMP	LDC35

	', )

IFDEF( `ROMVER', `		
	STA	PAGETAB,Y	;IF ROM VERSION, WRITE TO PLACE WITH SAME VAL
	', `			
	STA	-2		;IF NOT ROM VERSION, JUST WRITE TO FFFE
	')
	RTS

.DB 8,9
.DB 24,25
.DB 40,41
.DB 56,57
.DB 72,73
.DB 88,89
.DB 104,105
.DB 120,121

.DB 12,13
.DB 28,29
.DB 44,45
.DB 60,61
.DB 76,77
.DB 92,93
.DB 108,109
.DB 124,125

	PHA 
	TYA
	PHA
	LDA	ALTBANK
	STA	NMIBANK
	LDA	ALTINDX
	STA	NMIINDX		;SET RETURN POINT
	JSR	BACKFINISH
	JSR	NMI		;CALL THE NMI LOGIC
	LDA	NMIBANK
	LDY	NMIINDX
	JSR	SELPAGE
	PLA
	TAY
	PLA
	RTI	

	LDX	#H'FF
	TXS			;SET UP THE STACK
	LDA	#12
	STA	PAGETAB
	JMP	BOOT

.ORG	H'7FFA


	.DRW	PNMI		;NMI INTERRUPT (VERTICAL RETRACE INT)
	.DRW	PBOOT		;BOOT VECTOR
	.DRW	IRQRTI		;IRQ VECTOR

.ORG	0		;DO NOT CHANGE THIS ORG

INCLUDE( YOURBACK.ASM)	;BACKGROUNDS FROM ND.EXE
INCLUDE( YOURSND.ASM)	;SOUND DATA TO PUT IN THE SECOND ROM PAGE
INCLUDE( YOURCODE.ASM)	;ENTITY LANGUAGE CODE FOR THE SECOND PAGE

.CODE				;SPECIFY CODE SEGMENT IN CASE OF PAGEING


IFDEF( `BLOCKMODE', `
.ORG    64880   ;FD70H - JGT 01.25.90           (Was FDA0H)
        ', ` 
.ORG    64944   ;FDB0H - JGT 01.25.90           (Was FDE0H)
        ' )



USERPAGE:       
                lda     DATA2           ;high address.
                bmi     USERPG1         ;It's in Code Page 0.

                lda     ALTBANK
                ldy     ALTINDX
		JSR	SELPAGE

USERPG1:
                jsr     USERPG2

		JMP	BACKFINISH
                
USERPG2:
                lda     DATA2
                ora     #x'80           ;Correct address just in case.
                pha
                lda     DATA1
                pha
                rts                     ;Call the USERSUB
                
CMDLEN:
	.DB	2,5,4,4,3,4,3,2,3,2,2,3,3,2,2,2		;CMD00
	.DB	2,1,1,1,1,4,3,1,1,1,2,4,3,3,2,5		;CMD10
	.DB	3,1,4,4,4,5,1,3,4,2,4,4,2,3,1,2		;CMD20
	.DB	2,9,2,1,1,6,5,4,4,6,3,3,5,3,3,2		;CMD30
	.DB	3,5,3,2,1,4,2,2,2,3,2,4,2,3,3,2		;CMD40
	.DB	3,4,4,5,3,2,2,3,4,3,2,3,2,2,2,4		;CMD50 
	.DB	4,5,4,3,2,3,4,6,1,5,2,3,3,5,7,6		;CMD60
	.DB	10,2,2,2,5,4,2,7,3,1,2,5,2,3,1,7	;CMD70
	.DB	3,3,5,3,2,2,2,2,2,3,2,3,1,2,2,1		;CMD80
 	.DB	3,3,4,4,4,1,3,2,2,1,3,3,2,2,5,5		;CMD90
 	.DB	5,2,1,5,2,1,3,1,1,3,2,3,1,1,4,2		;CMDA0
 	.DB	1,1,2,3,3,1,6,1,1,3,3,3,3,2,1,3		;CMDB0
	.DB	3,2,3,1,2				;CMDC0


FILLCBUF:
	LDA	ENEMYPTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA			;SAVE IT
	BMI	FCB15
	ORA	#128
	STA	ENEMYPTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
FCB15:	LDY	#0	
	CPX	#0
	BNE	FCB17
	LDA	(ENEMYPTR),Y
	TAX			;GET THE COMMAND BYTE
	LDA	CMDLEN,X	;GET THE COUNT FOR THIS COMMAND
	TAX
FCB17:	STX	SUBSVAR1	;RETURN THE COUNT BYTE
FCB20:	LDA	(ENEMYPTR),Y
	STA	CMDBUF,Y	;FETCH LENGTH REQUESTED
	INY
	DEX
	BNE	FCB20
	PLA
	BMI	FCB30
	STA	ENEMYPTR+1	;RESTORE ORIGINAL BANK SPECIFICATION
BACKFINISH:			;YOU CAN GO HERE TO RTS WITH BACKBANK SELECTED
	LDA	BACKBANK
	LDY	BACKINDX
	JMP	SELPAGE
FCB30:	RTS	


FILLSTACK:
	TSX
	INX
	INX
	INX			;GET PLACE TO PUT THE DATA
	LDA	SUBSVAR2	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	FSK10
	ORA	#128
	STA	SUBSVAR2
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
FSK10:	LDY	#0	
FSK20:	LDA	(SUBSVAR1),Y
	STA	256,X			
	INY
	INX
	DEC	SUBSVAR3
	BNE	FSK20
	PLA
	BMI	FSK25
	STA	SUBSVAR2
	JMP	BACKFINISH
FSK25:	RTS	

LOADCOL:

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	LDC15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
LDC15:	CLC
	LDY	#0
LDC20:	LDA	(NMI_PTR),Y	;GET A BYTE
	STA	SCNBUF,X	;QUE IT UP
	INX
	LDA	NMI_PTR
	ADC	TMP_NMI2	;SKIP TO NEXT ROW IN DATA
	STA	NMI_PTR
	BCC	LDC30
	INC	NMI_PTR+1
	CLC
LDC30:	DEC	TMP_NMI1
	BNE	LDC20

LDC35:	PLA
	BMI	LDC40
	LDA	NMI_PTR+1
	EOR	#128
	STA	NMI_PTR+1
	JMP	BACKFINISH
LDC40:	RTS	


LOADPCOL:

IFDEF( `BLOCKMODE', `		;BLOCK MODE HAS A Y STARTING OFFSET

	LDY	#0
	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	LPC14
	ORA	#128
	STA	NMI_PTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
LPC14:	LDY	#0
LPC15:	LDA	(NMI_PTR),Y	;GET THE BYTE
	STA	TMP_NMI6,X	;QUE IT UP
	INX
	DEC	TMP_NMI1
	BEQ	LDC35		;SHARE SOME ENDING CODE
	LDY	#2
	JMP	LPC15
	
	', `

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	LPC14
	ORA	#128
	STA	NMI_PTR+1	;IN EITHER CASE, MAKE IT BE IN ROM
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
LPC14:	LDY	#0
LPC15:	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI4
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI3
	STA	SCNBUF,X
	INX
	LDA	#1		;WE ALWAYS JUST QUE 1 IN THIS CASE
	STA	SCNBUF,X
	INX

	LDA	(NMI_PTR),Y	;GET THE BYTE
	STA	SCNBUF,X		;QUE IT UP
	INX
	TYA
	CLC
	ADC	TMP_NMI2	;UPDATE INDEX WITHIN OUR DATA
	TAY
	BCC	LPC20
	INC	NMI_PTR+1


LPC20:	LDA	TMP_NMI3
	CLC
	ADC	#8		;SKIP TO NEXT PALETTE ROW
	STA	TMP_NMI3

 	DEC	TMP_NMI1
 	BNE	LPC15
	JMP	LDC35		;SHARE A HAPPY ENDING	

	' )


LOADROW:

IFDEF( `BLOCKMODE', `		

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	LDR15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
LDR15:	CLC
	LDY	#0
LDR20:	LDA	(NMI_PTR),Y	;GET A BYTE
	STA	SCNBUF,X	;QUE IT UP
	INX
	LDA	NMI_PTR
	ADC	#1		;SKIP TO NEXT COL IN DATA
	STA	NMI_PTR
	BCC	LDR30
	INC	NMI_PTR+1
	CLC
LDR30:	DEC	TMP_NMI1
	BNE	LDR20
	JMP	LDC35

	', )


SHIFTROW:

IFDEF( `BLOCKMODE', `		

	LDA	NMI_PTR+1	;GET HIGH OFFSET TO MAKE A PAGE
	PHA
	BMI	SHR15
	ORA	#128
	STA	NMI_PTR+1
	LDA	ALTBANK
	LDY	ALTINDX
	JSR	SELPAGE
SHR15:	LDY	#0
SHR20:	LDA	(NMI_PTR),Y	;GET A BYTE
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	
	ROR	A	
	ROR	SCNBUF,X	;SHIFT THE TOP NIBBLE INTO THE EXISTING BYTE
	INX
	LDA	NMI_PTR
	CLC
	ADC	#1		;SKIP TO NEXT COL IN DATA
	STA	NMI_PTR
	BCC	SHR30
	INC	NMI_PTR+1
SHR30:	DEC	TMP_NMI1
	BNE	SHR20
	JMP	LDC35

	', )


SELPAGE:
IFDEF( `ROMVER', `		
	STA	PAGETAB,Y	;IF ROM VERSION, WRITE TO PLACE WITH SAME VAL
	', `			
	STA	-2		;IF NOT ROM VERSION, JUST WRITE TO FFFE
	')
	RTS


PAGETAB:
.DB 8,9
.DB 24,25
.DB 40,41
.DB 56,57
.DB 72,73
.DB 88,89
.DB 104,105
.DB 120,121

.DB 12,13
.DB 28,29
.DB 44,45
.DB 60,61
.DB 76,77
.DB 92,93
.DB 108,109
.DB 124,125


PNMI:
	PHA 
	TYA
	PHA
	LDA	BACKBANK
	STA	NMIBANK
	LDA	BACKINDX
	STA	NMIINDX		;SET RETURN POINT
	JSR	BACKFINISH
	JSR	NMI		;CALL THE NMI LOGIC
	LDA	NMIBANK
	LDY	NMIINDX
	JSR	SELPAGE
	PLA
	TAY
	PLA
IRQRTI:
	RTI	


PBOOT: 	
	LDX	#H'FF
	TXS			;SET UP THE STACK
	LDA	#12
	STA	PAGETAB
	JMP	BOOT

.ORG	H'FFFA


	.DRW	PNMI		;NMI INTERRUPT (VERTICAL RETRACE INT)
	.DRW	PBOOT		;BOOT VECTOR
	.DRW	IRQRTI		;IRQ VECTOR

.ORG	H'8000		;CODE ROM PROGRAM ORIGIN.


.EQU	STATLEN,H'E7		;LENGTH TO WRITE TO STATUS LINE.  0 IF NOT
.EQU	STATROW,H'E8		;ROW TO WRITE AT
.EQU	STATCOL,H'E9		;COLUMN TO WRITE AT

.EQU	STATDATA,H'EA		;LOCATION OF DATA TO WRITE TO STATUS BAR

.EQU	WORLDSPOT,H'EC		;CURRENT LOCATION IN THE WORLD LIST.  USED
.EQU	SPOTCOL,H'EE		;FIRST COLUMN OF CURRENT BACKGROUND IN
.EQU 	BACKBASE,H'F0		;BACKGROUND DATA PTR

.EQU	BPBASE,H'F2 		;BACKGROUND PALETTE INFO PTR

.EQU	WORLDPTR,H'F4		;POINTER TO LIST OF BACKGROUNDS FOR THIS
				;WORLD.
.EQU	NMI_PTR,H'F6

.EQU	BPAL_BASE,H'F8		;BACKGROUND PALETTE REG DATA BASE PTR
.EQU	SPAL_BASE,H'FA		;SPRITE PALETTE REG DATA BASE PTR
.EQU	MAIN_PTR,H'FC		;POINTER FOR USE BY MAINLINE ROUTINES



.EQU	SUBSVAR1,H'FE		;VARIABLE FOR USE BY THE SUBS.  OK TO
.EQU	SUBSVAR2,H'FF		;USE FROM BOTH NMI AND NON-NMI LEVEL

.EQU	STATSPR,H'200		;SPRITE RAM.  H'200-H'2FF
.EQU	SPRAM,H'204		;SPRITE RAM AFTER SKIPING SPRITE #0

.EQU	SCNBUF,H'300		;SCREEN WRITE BUFFER.  LENGTH MAY CHANGE
.EQU	SCSIZE,H'60		;AMOUNT THAT BUFFER CAN HOLD

;360-37F USED BY KUNGFU FOR ENEMIES.

.EQU	SCCNT,H'380		;COUNT OF DATA IN BUFFER

.EQU	TOOMANY,H'381		;SET TRUE BY NMI IF LAST SCREEN PAINT HAD

.EQU	BPAL_BLINK,H'382	;BACKGROUND PALETTE CONTROL RAM
.EQU	BPAL_DEPTH,H'383
.EQU	BPAL_FREQ,H'384
.EQU	BPAL_INDX,H'385
.EQU	BPAL_CNT,H'386

.EQU	NEW_PAL,H'387		;BIT 01 SET IF NEW BACKGROUND PAL

.EQU	SPAL_BLINK,H'388	;BACKGROUND PALETTE CONTROL RAM
.EQU	SPAL_DEPTH,H'389
.EQU	SPAL_FREQ,H'38A
.EQU	SPAL_INDX,H'38B
.EQU	SPAL_CNT,H'38C

.EQU	J1FLAGS,H'38D		;JOYSTICK1 CURRENT STATE
.EQU	J2FLAGS,H'38E		;JOYSTICK2 CURRENT STATE. ON=BUTTON DOWN.

.EQU A_BUTTON,H'80		;80H = A button		EQUATES TO MAKE IT
.EQU B_BUTTON,H'40		;40H = B button		EASIER TO TEST J1FLAGS
.EQU SELECT,H'20		;20H = Select
.EQU START,H'10			;10H = Start
.EQU UP,8			;08H = Up
.EQU DOWN,4			;04H = Down
.EQU LEFT,2			;02H = Left
.EQU RIGHT,1			;01H = Right

.EQU	J1CHANGE,H'38F		;USED TO HOLD CHANGES IN JOYSTICK STATE
.EQU	J2CHANGE,H'390

.EQU	REPCNT,H'391		;AUTOREPEAT COUNT DOWN TIMER

.EQU	J1REPFLG,H'392		;HOLDS BIT FOR EACH J1 BUTTON AUTOREPEATING
.EQU	J2REPFLG,H'393		;HOLDS BIT FOR EACH J1 BUTTON AUTOREPEATING
.EQU	J1HOLD,H'394		;USED TO DELAY START OF AUTOREPEAT BY 1 REPEAT
.EQU	J2HOLD,H'395		;USED TO DELAY START OF AUTOREPEAT BY 1 REPEAT

.EQU	WORLD_HEIGHT,H'396	;TOTAL COMBINED HEIGHT OF WORLD IN ROWS

.EQU	DOUBLE_BIT,H'397	;THIS VARIABLE TRACKS THE VALUE OF REG2000'S

.EQU	DIDX,H'398 		;SIGNAL THAT WE JUST DID X SCROLL AND NEED

.EQU	END_ROW,H'399		;USED TO ADJUST SCROLL POSITIONS

.EQU	FETCHCOL,H'39A		;COLUMN WE NEED TO FETCH WITH BUILD_COL

.EQU	FETCHROW,H'39C		;ROW WE NEED TO FETCH ALONG WITH FETCHCOL

.EQU	WORLD_WIDTH,H'39E	;TOTAL COMBINED WIDTH OF WORLD IN COLUMNS 

.EQU	END_COL,H'3A0		;LAST LEFTMOST COLUMN FOR THE BACKGROUND
.EQU	RIGHTLIMIT,H'3A2	;RIGHTMOST LEGAL XBACK (PIXEL LOCATION)

.EQU	BACKVALID,H'3A4		;TRUE IF THE BACKGROUND IS VALID. MAKE_SCROLL

.EQU	SOLIDCHAR,H'3A5		;THE SOLID CHAR WE HIT WITH TESTPUT

.EQU	TESTX,H'3A6		;SAVED BY TESTPUT FOR USERS IN KUNGFU.ASM
.EQU	TESTY,H'3A7

.EQU	BOTLIMIT,H'3A8		;BOTTOM MOST PIZEL COLUMN FOR THE BACKGROUND

.EQU	BLOCK_WIDTH,H'3AA 	;BLOCK WIDTH OF WORLD IF BLOCK MODE

.EQU	BASESPRITE,H'3AB	;BASE SPRITE FOR USE BY SPRITE ROUTINES


.EQU	XWORLDSPOT,H'3AC
.EQU	XSPOTCOL,H'3AE
.EQU	XBACKBASE,H'3B0
.EQU	XBPBASE,H'3B2
.EQU	XBACKSIZE,H'3B4		;1 OR 2 SIZE OF BACKGROUND BLOCKS
.EQU	XBACKWIDE,H'3B5		;WIDTH IN BLOCKS OF BACKGROUND
.EQU	XBACKHIGH,H'3B6		;HEIGHT IN BLOCKS OF BACKGROUND
.EQU	XBPWIDE,H'3B7		;WIDTH OF PALETTE INFO ASSOCIATED WITH BACKGRND

.EQU	STARTSTAT,H'3B8		;SCROLL START FOR STATUS BAR (H'F0-ROWS UP)
.EQU	PUTBAR,H'3B9		;Y VALUE TO USE FOR THE SPRITE
.EQU	CUTOFF,H'3BA		;SCROLL VALUE TO USE TO CUT OFF BACKGROUND.
.EQU	STATBITS,H'3BB		;BITS FOR REG2000 FOR STATUS BAR
.EQU	SHAKEAMT,H'3BC		;MICRO BACKGROUND SCROLL ADJUSTMENT FROM
.EQU	BACKBITS,H'3BD		;BITS FOR REG2000 FOR SPRITES AND CHAR SET


.EQU	STATBANK,H'3BE		;STATUS BAR VIDEO BANK TO FEED TO PAGETAB
.EQU	STATINDX,H'3BF		;INDEX TO USE INTO PAGETAB.

.EQU	BACKBANK,H'3C0		;BELOW STATUS BAR VALUE TO FEED TO PAGETAB
.EQU	BACKINDX,H'3C1

.EQU	ALTBANK,H'3C2
.EQU	ALTINDX,H'3C3

.EQU	NMIBANK,H'3C4		;FOR NMI INTERRUPT LOGIC
.EQU	NMIINDX,H'3C5

.EQU	CURSOR,H'3C6		;CURSOR FOR TEXTWRITE COMMAND

.EQU	LINKNEXT,H'3C8		;FOR NEXTLINKED COMMAND
.EQU	KEEPEM,H'3C9		;USED FOR THE PRIORITY BIT AND WORLDGOTO


.EQU	TMP_NMI1,H'3D0		;TEMPORARY VARIABLES TO USE DURING NMI INT.
.EQU	TMP_NMI2,H'3D1		;RULES FOR USE:  EVEN USER SUBS MAY USE
.EQU	TMP_NMI3,H'3D2		;THESE VARIABLES BUT NO ROUTINE SHOULD 
.EQU	TMP_NMI4,H'3D3		;EXPECT ANY VALUES TO STAY HERE WHEN ANOTHER
.EQU	TMP_NMI5,H'3D4		;SUB IS CALLED UNLESS THAT ROUTINE 
.EQU	TMP_NMI6,H'3D5		;SPECIFICALLY STATES THAT THE VARIABLES ARE
.EQU	TMP_NMI7,H'3D6		;NOT USED.  OK TO USE OUTSIDE NMI IF YOU
.EQU	TMP_NMI8,H'3D7		;DISABLE NMI INTS THE WHOLE TIME.
.EQU	TMP_NMI9,H'3D8		
.EQU	TMP_NMIA,H'3D9
.EQU	TMP_NMIB,H'3DA
.EQU	TMP_NMIC,H'3DB
.EQU	TMP_NMID,H'3DC
.EQU	TMP_NMIE,H'3DD

.EQU	SUBSVAR5,H'3DE		
.EQU	SUBSVAR6,H'3DF
.EQU	SUBSVAR3,H'3E0		;NON-PTR CAPABLE SUBS FOR USE FROM ANY LEVEL.
.EQU	SUBSVAR4,H'3E1		

.EQU	MATH1,H'3E2		;TEMPORARY VARIABLES FOR USE BY MATH ROUTINES.
.EQU	MATH2,H'3E3		;SAVED EACH NMI AND RESTORED TO ALLOW ALL
.EQU	MATH3,H'3E4		;TO USE MATH ROUTINES.  THESE MAY BE USED
.EQU	MATH4,H'3E5		;AS TEMP VARIABLES ALSO BUT WILL BE CHANGED

.EQU	STATDELAY,H'3E6		;DELAY AFTER COLLISION DETECTION BEFORE

.EQU	FOUNDSOME,H'3E7 	;USED BY FEED_SOUND

.EQU	REG4015,H'3E8		;VOICE ENABLE REG CURRENT STATE

.EQU	SCRLDIF,H'3E9		;FOR USE BY SCROLL ROUTINE.

.EQU	FONT2,H'3EA		;STATUS BYTE FOR 2 HIGH FONT ROUTINES.

.EQU	MOVEBACK,H'3EB		;SET TRUE IF BACKGROUND NEEDS MOVING.

.EQU	SPYADJ,H'3EC		;CENTERING AMOUNT FOR SPRITES AS A RESULT

.EQU	ROTATEFLG,H'3ED 	;SET TO 0 TO TURN OFF ROTATION

.EQU	XBACK,H'3EE		;USER SET DESIRED X PIXEL LOCATION IN BACKGND

.EQU	YBACK,H'3F0		;USER SET DESIRED Y

.EQU	ROTATING,H'3F2 		;TRUE IF WE ARE ROTATING THE SPRITES AND

.EQU	CURX,H'3F3		;CURRENTLY DRAWN X PIXEL BACKGROUND LOCATION
.EQU	CURY,H'3F5		;CURRENTLY DRAWN Y PIXEL LOCATION

.EQU	BACKSIZE,H'3F7		;1 OR 2 SIZE OF BACKGROUND BLOCKS
.EQU	BACKWIDE,H'3F8		;WIDTH IN BLOCKS OF BACKGROUND
.EQU	BACKHIGH,H'3F9		;HEIGHT IN BLOCKS OF BACKGROUND
.EQU	BPWIDE,H'3FA		;WIDTH OF PALETTE INFO ASSOCIATED WITH BACKGRND

.EQU	DRUMLOCK,H'3FB 		;BITS TO LOCK DRUM OUT FROM USING A SPECIFIC

.EQU	XSCROLL,H'3FC		;X SCREEN SCROLL VALUE
.EQU	YSCROLL,H'3FD		;Y SCREEN SCROLL VALUE WHEN BACKGROUND ACTIVE
.EQU	REG2001,H'3FE		;VALUE TO WRITE TO H'2001 TO ENABLE VIDEO
.EQU	REG2000,H'3FF		;THE VALUE WE WRITE TO H'2000 MINUS NMI ENABLE


.EQU	ANIM_WIDE,11		;WIDTH OF EACH ENTRY.  NOT USER CHANGABLE.
.EQU	SPMEM,SPSLOTS*ANIM_WIDE	;AMOUNT OF RAM USED BY THE SPRITE SLOTS
.EQU	ANIM_RAM,H'400		;BASE SLOT OF ANIMATION/SPRITE RAM
.EQU	FB,0			;FLAG BYTE: 	0=SLOT AVAILABLE,
.EQU	AF,1			;AUXILARY FLAGS:
.EQU	PTRL,2			;WORD PTR TO DATA OR ANIMATION LIST
.EQU	PTRH,3
.EQU	BS,4			;IF SPRITE, BASE SPRITE*4 INDEX (BYTE).
.EQU	NS,5			;IF SPRITE, NUMBER OF SPRITES (BYTE).
.EQU	FR,6			;CURRENT ANIMATION FRAME (BYTE)
.EQU	CN,7			;COUNT DOWN TO NEXT FRAME CHANGE (BYTE)
.EQU	RL,8			;RELOAD VALUE FOR COUNT DOWN (BYTE). INITIALLY
.EQU	SL,9			;SOLID CHAR VALUE.  ONLY VALID IF SOLID
.EQU	PA,10			;PREALLOCATION VALUE.  INDICATES NUMBER


.EQU	SND_WIDE,8		;WIDTH OF EACH ENTRY.  NOT USER CHANGABLE.
.EQU	SNDMEM,SNDSLOTS*SND_WIDE ;AMOUNT OF RAM USED BY THE SPRITE SLOTS
.EQU	SND_RAM,H'400+SPMEM	;BASE SLOT OF ANIMATION/SPRITE RAM
.EQU	SF,0			;SOUND FLAG:  BIT 80H SET IF SLOT IN USE.
.EQU	ST,1			;SOUND TIMER.  LOADED WITH NOTE OR PAUSE
.EQU	SBL,2			;BASE POINTER (WORD) TO THE ORIGINAL SOUND
.EQU	SBH,3			;	      STRUCTURE PASSED IN CALL.
.EQU	SOL,4			;SOUND OFFSET OF CURRENT PLAY LOCATION.			
.EQU	SOH,5
.EQU	SI,6			;INSTRUMENT CURRENTLY ACTIVE.  USED TO 
.EQU	LOP,7			;LOOP COUNTER FOR THE LOOP COMMAND

;THESE SLOTS END AT 4D8.

.EQU	VIDTYPE,H'4D8		;0 FOR PAGE 0, 1 FOR PAGE 1, -1 FOR 
.EQU	STATTYPE,H'4D9		;TYPE OF STATUS BAR COMMAND (FILL, WRITE...)

.EQU	STATHI,H'4DA 		;HIGH BYTE OF STATUS LOCATION FOR SCNBUF
.EQU	STATLO,H'4DB 		;LOW BYTE OF STATUS LOCATION FOR SCNBUF

.EQU	 ALLOCATION,H'4DC	;PREALLOCATION VALUE USED BY INITSPRT

.EQU	CLOCK,H'4DD		;LOADED WITH -1 AFTER INITIAL KEY CIRCUIT

.EQU	METHOD,H'4DE		;KEY CIRCUIT METHOD USED:

.EQU	PULSEMETHOD,H'0A
.EQU	CURRENTMETHOD,H'0B
.EQU	LASTTRY,H'0C

.EQU	VERIFIER,H'4DF		;KEY CIRCUIT METHOD VERIFIER.  METHOD XOR -1.
				


BOOT:	SEI			;DISALLOW IRQ INTERRUPTS

	LDA	#0
	STA	H'2000		;MAKE SURE NMI INTS ARE OFF


	JSR	VERT_WAIT	
	JSR	VERT_WAIT	;WAIT FOR 2 TO MAKE SURE BIT IS VALID

	LDA	#6
	STA	H'2001


	LDA	METHOD
	EOR	VERIFIER
	CMP	#-1
	BEQ	TRIED_SOME


TRYPULSE:
 	LDA	#PULSEMETHOD|H'80
	STA	METHOD
	EOR	#-1
	STA	VERIFIER
	JMP	TRY35


TRIED_SOME:
	LDA	METHOD
	CMP	#PULSEMETHOD
	BEQ	TRY35		;IF SUCCESSFUL PULSE ON 35, USE IT AGAIN.
	CMP	#CURRENTMETHOD
	BEQ	TRY70		;IF CURRENT ON 70 WORKS, USE IT AGAIN.

	CMP	#PULSEMETHOD|H'80	;SEE IF JUST A TRY AT PULSE ON 35
	BNE	TRYPULSE		;IF NOT, TRY THAT AGAIN

 	LDA	#CURRENTMETHOD|H'80
	STA	METHOD
	EOR	#-1
	STA	VERIFIER		;OTHERWISE TRY CURRENT ON 70.
	JMP	TRY70


TRY35:
	JSR	XPULSE
	JSR	XPULSE
	JMP	XEXIT


TRY70:	LDA	#12
	STA	TRY70+1
	JMP	XEXIT


XPULSE:	LDA	#8
	STA	XPULSE+1
	JSR	DELAY005
ZEROX:	LDA	#0
	STA	ZEROX+1
	JMP	DELAY005


DELAY005:
      	LDY	#4
	LDX	#58		;(MAKES 3*256 + 1*58)
XXX10:	DEX
	BNE	XXX10
	DEY
	BNE	XXX10
	RTS

XEXIT:	
	LDA	#-1
	STA	CLOCK		;SET FULL TIME TO TRY OUT KEY CHIP METHOD


	LDA	X'2002
	LDA	#X'3F		;Background palette, HI addr.
	STA	X'2006
	LDA	#X'00		;Background palette, LO addr.
	STA	X'2006

	LDY	#31
	LDA	#X'0E		;BLACK.
BOOTJGT:STA	X'2007		;Store it.
	DEY
	BPL	BOOTJGT


	LDA	#0
	STA	NEW_PAL		;RESET FLAG OF PALETTE NEEDS INIT
	STA	SCCNT		;ZERO DATA TO WRITE TO SCREEN
	STA	XSCROLL
	STA	YSCROLL		;ZERO SCROLL
	STA	CURX
	STA	CURY		;ZERO BACKGROUND SCROLL LOW VALUES FOR PUTSPRT
	STA	BACKVALID
	STA	MOVEBACK	;RESET FLAG TO SCROLL BACKGROUND
	STA	BPAL_BLINK
	STA	SPAL_BLINK	;PREVENT PALETTE UPDATES
	STA	J1FLAGS
	STA	J2FLAGS
	STA	J1HOLD
	STA	J2HOLD
	STA	J1REPFLG
	STA	J2REPFLG	;RESET BUTTON LOGIC
	STA	REG2000		;AND ZERO SCREEN PAGE 
	STA	DOUBLE_BIT
	STA	REG4015		;AND SOUND ENABLE REG
	STA	SPYADJ
	STA	BASESPRITE
	STA	ROTATEFLG
	STA	ROTATING
	STA	SHAKEAMT
	STA	STATBANK
	STA	STATBITS
	STA	BACKBANK
	STA	BACKBITS

	LDA	#REPRATE
	STA	REPCNT		;RELOAD THE JOYSTICK REPEAT RATE

	LDA	#10
	STA	STATDELAY

	LDA	#H'1E
	STA	REG2001		;SET UP FOR SPRITES, BACKGROUND, NO ODD COLORS
				;AND 31 COL MODE FOR ALL.

	JSR	HIDESPRITES	;FREE UP AND HIDE THE SPRITES
	JSR	ZERO_ANIM	;CLEAR THE ANIMATION RAM
	JSR	ZERO_SOUND


	JSR	USER_BOOT


	JSR	RESUME_NMI


B1000:	JSR	USER_MAINLINE
	JMP	B1000


NMI:	LDA	#06		
	STA	H'2001		;DISABLE VIDEO TO ALLOW SCREEN ACCESS

	LDA	PUTBAR		;GET ROW TO PUT IT ON
	SEC
	SBC	SHAKEAMT
	STA	STATSPR		;ALWAYS REPOSITION THE TOP SPRITE IF STAT BAR

	LDA	ROTATING	;DON'T DO THE DMA IF ROTATING FLAG SET
	BNE	N10
	STA	H'2003		;ZERO SPRITE DMA BASE REG
	LDA	#STATSPR >> 8	;GET PAGE OF SPRITE RAM
	STA	H'4014		;START THE SPRITE RAM DMA TRANSFER

N10:	JSR	STOP_NMI		;DISABLE NMI

	LDA	H'2002		;RESET ADDRESS REG SELECT FOR THROUGHOUT NMI.
	AND	#H'20
	STA	TOOMANY		;KEEP SPRITE FLICKER BIT

	TXA	
	PHA
	TYA
	PHA			;SAVE THE REGISTERS

	JSR	WRITE_SCNBUF	;WRITE OUT ANY DATA IN SCNBUF
 	LDA	#0
	STA	SCCNT

	LDA	MATH1
	PHA
	LDA	MATH2
	PHA			
	LDA	MATH3
	PHA			
	LDA	MATH4
	PHA			;SAVE MATH SUBS VARIABLES

	JSR	MAKE_SCROLL	;SCREEN UPDATED, MAKE ANY NEW SCROLL NEEDED


N100: 	JSR	FINISH_TOP

	
	LDA	SUBSVAR1
	PHA
	LDA	SUBSVAR2
	PHA
	LDA	SUBSVAR3
	PHA
	LDA	SUBSVAR4
	PHA
	LDA	SUBSVAR5
	PHA			
	LDA	SUBSVAR6
	PHA			;SAVE SUB VARIABLES SO THAT THE SUBS MAY
				;BE USED FROM ANY LEVEL.

	LDA	FETCHCOL
	PHA
	LDA	FETCHCOL+1
	PHA
	LDA	FETCHROW
	PHA

	JSR	SWAPPTRS	;SWAP THE IMPORTANT BACKGROUND SCANNERS


	DEC	CLOCK
	BNE	N150
	LDA	METHOD		;IF ZERO, WE NEED TO ESTABLISH KEY METHOD?
	AND	#H'7F
	STA	METHOD		;SET AS THE METHOD OF CHOICE
	EOR	#-1
	STA	VERIFIER	;SET AS VALID FOR NEXT BOOT


N150:	LDA	#1
	STA	H'4016
	LDA	#0
	STA	H'4016		;LATCH A VALUE TO SHIFT.  ALSO LATCHES 4017.

	LDA	#0
	STA	J1CHANGE	;ZERO RESULT
	LDX	#8
N200:	LDA	H'4016
	ROR	A
	ROL	J1CHANGE	;MOVE BIT UP INTO OUR BYTE
	DEX
	BNE	N200
	LDA	J1CHANGE	;GET NEW VALUE
	TAX			;SAVE NEW VALUE
	EOR	J1FLAGS		;GET CHANGES
	STA	J1CHANGE	;SAVE CHANGES
	STX	J1FLAGS		;AND CURRENT STATE

	LDA	#0
	STA	J2CHANGE	;ZERO RESULT
	LDX	#8
N210:	LDA	H'4017
	ROR	A
	ROL	J2CHANGE	;MOVE BIT UP INTO OUR BYTE
	DEX
	BNE	N210
	LDA	J2CHANGE	;GET NEW VALUE
	TAX			;SAVE NEW VALUE
	EOR	J2FLAGS		;GET CHANGES
	STA	J2CHANGE	;SAVE CHANGES
	STX	J2FLAGS		;AND CURRENT STATE


	LDA	J1FLAGS
	AND	J1REPFLG	
	STA	J1REPFLG
	LDA	J1FLAGS
	AND	J1HOLD
	STA	J1HOLD		;RESET ANY NO LONGER DOWN IN JOYSTICK 1 FLAGS

	LDA	J2FLAGS
	AND	J2REPFLG
	STA	J2REPFLG
	LDA	J2FLAGS
	AND	J2HOLD
	STA	J2HOLD		;RESET ANY NO LONGER DOWN IN JOYSTICK 2 FLAGS


	DEC	REPCNT		;COUNT DOWN THE REPEAT COUNTER
	BNE	N215		;SKIP IF NOT TIME TO REPEAT AGAIN.
	LDA	#REPRATE
	STA	REPCNT		;RELOAD IT

	LDA	J1REPFLG	;GET THE REPEATING KEYS
	ORA	J1CHANGE
	STA	J1CHANGE	;SET AS IF ITS A CHANGED KEY

	LDA	J2REPFLG	
	ORA	J2CHANGE
	STA	J2CHANGE

	LDA	J1HOLD		;GET KEYS WAITING TO AUTOREPEAT NEXT PASS
	AND	#J1REPENA	;BUT ONLY WANT THOSE ENABLED TO REPEAT
	STA	J1REPFLG	;SET TO REPEAT NEXT COUNT
	LDA	J1FLAGS
	STA	J1HOLD		;MOVE CURRENT STATE INTO THE HOLDING FLAG

	LDA	J2HOLD		;GET KEYS WAITING TO AUTOREPEAT NEXT PASS
	AND	#J2REPENA	;BUT ONLY WANT THOSE ENABLED TO REPEAT
	STA	J2REPFLG	;SET TO REPEAT NEXT COUNT
	LDA	J2FLAGS
	STA	J2HOLD		;MOVE CURRENT STATE INTO THE HOLDING FLAG


N215: 	LDA	J1CHANGE	;GET JOYSTICK 1 CHANGES
	AND	J1FLAGS		
	BEQ	N240		;SKIP IF NO JOYSTICK CHANGES THIS PASS.

	ROR	J1CHANGE
	BCC	N220
	JSR	RIGHT1
N220:	ROR	J1CHANGE
	BCC	N221
	JSR	LEFT1
N221:	ROR	J1CHANGE
	BCC	N222
	JSR	DOWN1
N222:	ROR	J1CHANGE
	BCC	N223
	JSR	UP1
N223:	ROR	J1CHANGE
	BCC	N224
	JSR	STRT1
N224:	ROR	J1CHANGE
	BCC	N225
	JSR	SEL1
N225:	ROR	J1CHANGE
	BCC	N226
	JSR	B1		
N226:	ROR	J1CHANGE
	BCC	N240
	JSR	A1

N240:	LDA	J2CHANGE	;GET JOYSTICK 2 CHANGES
	AND	J2FLAGS		
	BEQ	N260

	ROR	J2CHANGE
	BCC	N250
	JSR	RIGHT2
N250:	ROR	J2CHANGE
	BCC	N251
	JSR	LEFT2
N251:	ROR	J2CHANGE
	BCC	N252
	JSR	DOWN2
N252:	ROR	J2CHANGE
	BCC	N253
	JSR	UP2
N253:	ROR	J2CHANGE
	BCC	N254
	JSR	STRT2
N254:	ROR	J2CHANGE
	BCC	N255
	JSR	SEL2
N255:	ROR	J2CHANGE
	BCC	N256
	JSR	B2
N256:	ROR	J2CHANGE
	BCC	N260
	JSR	A2


N260:  	LDA	BPAUSE		;IF PAUSED, DON'T DO ANY OF IT.
	BNE	N380

	JSR	USER_NMI
 	JSR	DOSCRL		;SCROLL THE BACKGROUND IF NEEDED
	JSR	DOPAL		;UPDATE PALETTES IF NEEDED

	LDA	ROTATING	;DON'T DO THE DMA IF ROTATING FLAG SET
	BNE	N265
	JSR	CHECK_ANIM	;SEE IF ANIMATIONS NEED PROCESSING
N265:
	JSR	FEED_SOUND	;FEED THE SOUND CHIP


N380: 	JSR	SWAPPTRS	;SWAP THE IMPORTANT BACKGROUND SCANNERS

	PLA
	STA	FETCHROW
	PLA	
	STA	FETCHCOL+1
	PLA
	STA	FETCHCOL

 	PLA
 	STA	SUBSVAR6
 	PLA
 	STA	SUBSVAR5
 	PLA
 	STA	SUBSVAR4
 	PLA
 	STA	SUBSVAR3
 	PLA
 	STA	SUBSVAR2
 	PLA
 	STA	SUBSVAR1	

	PLA
 	STA	MATH4
 	PLA
 	STA	MATH3
 	PLA
 	STA	MATH2
 	PLA	
 	STA	MATH1

 	PLA
 	TAY
 	PLA
	TAX

	JMP	RESUME_NMI	;WE RTS TO PNMI WHICH RTIs


SWAPPTRS:
	LDA	WORLDSPOT
	LDX	XWORLDSPOT
	STA	XWORLDSPOT
	STX	WORLDSPOT

	LDA	WORLDSPOT+1
	LDX	XWORLDSPOT+1
	STA	XWORLDSPOT+1
	STX	WORLDSPOT+1

	LDA	SPOTCOL
	LDX	XSPOTCOL
	STA	XSPOTCOL
	STX	SPOTCOL

	LDA	SPOTCOL+1
	LDX	XSPOTCOL+1
	STA	XSPOTCOL+1
	STX	SPOTCOL+1

	LDA	BACKBASE
	LDX	XBACKBASE
	STA	XBACKBASE
	STX	BACKBASE

	LDA	BACKBASE+1
	LDX	XBACKBASE+1
	STA	XBACKBASE+1
	STX	BACKBASE+1

	LDA	BPBASE
	LDX	XBPBASE
	STA	XBPBASE
	STX	BPBASE

	LDA	BPBASE+1
	LDX	XBPBASE+1
	STA	XBPBASE+1
	STX	BPBASE+1

	LDA	BACKSIZE
	LDX	XBACKSIZE
	STA	XBACKSIZE
	STX	BACKSIZE

	LDA	BACKWIDE
	LDX	XBACKWIDE
	STA	XBACKWIDE
	STX	BACKWIDE

	LDA	BACKHIGH
	LDX	XBACKHIGH
	STA	XBACKHIGH
	STX	BACKHIGH

	LDA	BPWIDE
	LDX	XBPWIDE
	STA	XBPWIDE
	STX	BPWIDE

	RTS


TOPSPRITE:
	LDA	PUTBAR		;GET ROW TO PUT IT ON
	STA	STATSPR
	LDA	#1		;SET SPRITE TO CREEP OUT OF INVISIBLE FIRST 
	STA	STATSPR+3	;COLUMN BY ONLY 1 PIXEL.
	LDA	#STATSPRITE	;AND GET A SOLID LINE SPRITE
	STA	STATSPR+1
	LDA	#H'28		;PUT IT BEHIND ANYTHING ELSE, MARK IN USE.
	STA	STATSPR+2
TPS10:	RTS


FINISH_TOP:

	LDA	STARTSTAT	;SEE IF WE HAVE A STATUS BAR
	BNE	FT01		;IF SO, GO MAKE ONE

	LDA	XSCROLL
	STA	H'2005		;IF NOT, SELECT THE NORMAL X SCROLL
	LDA	YSCROLL
	STA	H'2005		;SELECT THE NORMAL Y SCROLL
	LDA	REG2001
	STA	H'2001		;ENABLE VIDEO 
	JMP	FT35

FT01:

.EQU	HEX27,		H'27
.EQU	HEX40,		H'40
.EQU	HEXA0,		H'A0
.EQU	HEXE7,		H'E7
.EQU	HEXFE,		H'FE
.EQU	HEX2000,	H'2000
.EQU	HEX2001,	H'2001
.EQU	HEX2002,	H'2002
.EQU	HEX2005,	H'2005
.EQU	HEX2006,	H'2006
.EQU	HEX2007,	H'2007
IFDEF( `XTOPSTAT', `
	LDA	HEX2002
	LDA	#HEX27
	STA	HEX2006
	LDA	#HEXA0	
	STA	HEX2006		;ADDRESS LAST ROW OF SCREEN BUFFER, FIRST CHAR
	LDA	#STATCHAR
	STA	HEX2007		;AND WRITE OUT THE CHAR TO DETECT AS SOLID

 
	LDA	STATBANK
	LDY	STATINDX
	JSR	SELPAGE		;SELECT THE PAGE ACCORDING TO ROM OR ROMLESS

	LDA	REG2000
	AND	#HEXE7
	ORA	STATBITS
	STA	REG2000		;SET UPPER/LOWER BANK BITS FOR THE STATUS
				;BAR VIDEO BANK.

	AND	#HEXFE
	STA	HEX2000	;SELECT FIRST SCREEN PAGE BUT SCROLL TO LAST PIXEL

	LDA	REG2001
	STA	HEX2001	;ENABLE VIDEO 

	LDA	#255	;SET SCROLL THAT JUST MAKES 1 PIXEL TO RIGHT OF
	STA	HEX2005	;THE INVISIBLE ZONE SO WE CAN GET 1 PIXEL COLLISION
	LDA	STARTSTAT	
	CLC
	ADC	SHAKEAMT
	STA	HEX2005		;MOVE VERTICAL ALONG WITH SHAKE 


	LDY	#10
	LDA	#HEX40
FT31:	BIT	HEX2002
	BEQ	FT32		;WAIT FOR 40H TO GO OFF
	DEX
	BNE	FT31		;OR FOR A TIMEOUT
	DEY
	BNE	FT31
	JMP	FT33

	LDY	#10
FT32:	BIT	HEX2002
	BNE	FT33
	DEX
	BNE	FT32
	DEY
	BNE	FT32


FT33:	LDX	STATDELAY
FT33A:	DEX
	BNE	FT33A		;DONT KNOW WHY BUT DELAY CLEARS UP JUNK

	LDA	XSCROLL
	STA	HEX2005		;SELECT THE NORMAL X SCROLL
	LDA	YSCROLL
	STA	HEX2005		;SELECT THE NORMAL Y SCROLL
	', )

FT35:	LDA	REG2000
	AND	#H'E7
	ORA	BACKBITS
	STA	REG2000		;SET UPPER/LOWER BANK BITS FOR THESE SETS
	STA	H'2000		;FIX THE PAGE # TO WHAT USER WANTED

	JMP	BACKFINISH	;SELECT THE PAGE ACCORDING TO ROM OR ROMLESS


.EQU	LC,H'00
.EQU	LCs,H'01
.EQU	LDb,H'01
.EQU	LD,H'02
.EQU	LDs,H'03
.EQU	LEb,H'03
.EQU	LE,H'04
.EQU	LF,H'05
.EQU	LFs,H'06
.EQU	LGb,H'06
.EQU	LG,H'07
.EQU	LGs,H'08
.EQU	LAb,H'08
.EQU	LA,H'09
.EQU	LAs,H'0A
.EQU	LBb,H'0A
.EQU	LB,H'0B
.EQU	C,H'0C
.EQU	Cs,H'0D
.EQU	Db,H'0D
.EQU	D,H'0E
.EQU	Ds,H'0F		
.EQU	Eb,H'0F
.EQU	E,H'10
.EQU	F,H'11
.EQU	Fs,H'12
.EQU	Gb,H'12
.EQU	G,H'13	       	;NOTES (CENTER AROUND INSTRUMENT RANGE)
.EQU	Gs,H'14
.EQU	Ab,H'14
.EQU	Ax,H'15		;SPECIAL CASE.  A WAS REGISTER INDICATOR.  USE Ax.
.EQU	As,H'16
.EQU	Bb,H'16
.EQU	B,H'17
.EQU	HC,H'18
.EQU	HCs,H'19	;s MEANS SHARP (#)
.EQU	HDb,H'19	;b MEANS FLAT
.EQU	HD,H'1A
.EQU	HDs,H'1B
.EQU	HEb,H'1B
.EQU	HE,H'1C
.EQU	HF,H'1D
.EQU	HFs,H'1E
.EQU	HGb,H'1E
.EQU	PAUSE,H'1F

.EQU	N16,B'00000000		;NOTE DURATIONS.  USE BY ADDING (Gs+N16)
.EQU	N8,B'00100000
.EQU	N4,B'01000000
.EQU	N2,B'01100000
.EQU	N1,B'10000000

.EQU	BASE_HARPSI,B'10100000
.EQU	HARPSI,B'10100001
.EQU	HIGH_HARPSI,B'10100010
.EQU	BASE_STRING,B'10100011
.EQU	STRING,B'10100100
.EQU	HIGH_STRING,B'10100101
.EQU	BASE_ELECPIANO,B'10100110
.EQU	ELECPIANO,B'10100111
.EQU	HIGH_ELECPIANO,B'10101000	;INSTRUMENT SELECT COMMANDS
.EQU	BASE_SLIDER,B'10101001
.EQU	SLIDER,B'10101010
.EQU	HIGH_SLIDER,B'10101011
.EQU	BASE_BEE,B'10101100
.EQU	BEE,B'10101101
.EQU	HIGH_BEE,B'10101110
.EQU	BASE_PIANO,B'10101111
.EQU	PIANO,B'10110000
.EQU	HIGH_PIANO,B'10110001
.EQU	BASE_ARCADE,B'10110010
.EQU	ARCADE,B'10110011
.EQU	HIGH_ARCADE,B'10110100

.EQU	SOUNDLOOP,B'11000000	;LOOP COMMAND
.EQU	NODRUMS,B'11000010	;DISALLOW DRUMS IN THIS VOICE CHANNEL
.EQU	ALLOWDRUMS,B'11000011

.EQU	VOICE0,B'11100000
.EQU	VOICE1,B'11100001	;USED TO SELECT A REGISTER SET (VOICE).
.EQU	VOICE2,B'11100010
.EQU	VOICE3,B'11100011

.EQU	REPLAY,B'11100100	;USED TO REPEAT THE SOUND STRING OR END IT.
.EQU	ENDPLAY,B'11101000

.EQU	LOADREG0,B'11101100
.EQU	LOADREG1,B'11101101	;USED TO HARD CODE LOADING OF REGISTERS
.EQU	LOADREG2,B'11101110	;IN CURRENTLY SELECTED REGISTER SET (VOICE).
.EQU	LOADREG3 ,B'11101111

.EQU	STOPVOICE,B'11110000
.EQU	STARTVOICE,B'11110100 	;USED TO SILENCE OR ACTIVATE A VOICE

.EQU	PERCUSSION,B'11111000	;USED TO SELECT THE PERCUSSION INSTRUMENTS

.EQU	LOADALL,B'11111001	;USED TO SPECIFY LOADING ALL 4 REGS

.EQU	WAIT,B'11111011		;USED TO DELAY AFTER LOADALL OR LOADREGx


PLAY:  	STX	SUBSVAR1
	STY	SUBSVAR2	;SAVE ENTRY POINTERS
	JSR	SNDINDX		;IN RANGE?
	BEQ	P10
	RTS

P10:	LDA	SND_RAM+SF,X	;IN USE?
	BPL	P20
	LDA	#1		;IF IT IS, RETURN 1
	RTS

P20:	LDA	#1
	STA	SND_RAM+ST,X	;SET NEXT NMI TO ACTIVATE SOUND
	LDA	#0
	STA	SND_RAM+SI,X	;SET INSTRUMENT 0 AS DEFAULT
	STA	SND_RAM+LOP,X	;ZERO LOOP COUNTER
	LDA	SUBSVAR1
	STA	SND_RAM+SBL,X
	STA	SND_RAM+SOL,X	;SET LOW OFFSET
	LDA	SUBSVAR2
	STA	SND_RAM+SBH,X
	STA	SND_RAM+SOH,X	;SET HIGH OFFSET
	LDA	#H'C0
	STA	SND_RAM+SF,X	;SET AS ACTIVE SOUND STRUCTURE BUT NO REG.
	RTS


ZERO_SOUND:
 	LDA	#0
	STA	DRUMLOCK
	TAX
ZS10:	STA	SND_RAM,X
	INX
	CPX	#SNDMEM		;SEE IF DONE
	BNE	ZS10
	RTS


SILENCE:
	CMP	#-1		;SILENCE ALL?
	BNE	S10

ALLSILENCE:
	LDA	#0
S5:	PHA
	JSR	SILENCE		;IF SO, LOOP WITH ALL VALUES
	BNE	S7
	PLA
	CLC
	ADC	#1
	JMP	S5
S7:	PLA
	LDA	#0		;AND RETURN OK.
	RTS

S10:	JSR	SNDINDX
	BEQ	S20	
	RTS			;IF BAD INDEX, RETURN -1


S20:  	LDA	SND_RAM+SF,X	;GET THE FLAG BYTE
	BPL	S50		;SKIP IF NOT IN USE


	TAY			;SAVE A COPY
	AND	#H'60		;SEE IF NOT ASSIGNED OR IF SUSPENDED
	BEQ	S25		;SKIP IF TRULY ACTIVE
	LDA	#0
	STA	SND_RAM+SF,X	;IF INACTIVE, JUST FREE IT UP
	JMP	S50		;IF THIS ONE'S INACTIVE, IT DIDN'T SUSPEND ANY

S25:  	JSR	DISABLE_VOICE	;IF ACTIVE, DISABLE IT'S VOICE
	LDA	SND_RAM+SF,X	;GET BACK IT'S FLAG
	PHA			;SAVE THE FLAG
	LDA	#0
	STA	SND_RAM+SF,X	;FREE UP THIS SOUND STRUCTURE
	PLA
	AND	#H'1F		;KEEP BASE OF REGISTERS IN USE
	STA	SUBSVAR1	;SAVE HERE FOR COMPARE TO ONES WE FIND
	CMP	#H'1F		;PERCUSSION?
	BEQ	S50

	LDX	#0		;START AT LOWEST SLOT

S30:	TXA
	PHA
	LDA	SND_RAM+SF,X	;GET ITS FLAG BYTE
	BPL	S42		;IF NOT IN USE, SKIP IT

	AND	#H'20		;SEE IF SUSPENDED
	BEQ	S42		;WE DON'T CARE UNLESS IT IS
	LDA	SND_RAM+SF,X
	AND	#H'1F		;GET THE VOICE IT WAS USING
	EOR	SUBSVAR1	;SEE IF SAME AS OURS
	BNE	S42		;IF NOT, WE DON'T CARE
	PLA			;IF IT WAS, DISCARD SLOT INDEX
	JSR	INITSND		;AND INITIALIZE IT
	JSR	ENABLE_VOICE
	LDA	SND_RAM+SF,X
	AND	#H'DF
	STA	SND_RAM+SF,X	;AND MARK AS NOT SUSPENDED ANY MORE
	JMP	S50

S42:	PLA
	CLC
	ADC	#SND_WIDE
	TAX
	CMP	#SND_WIDE*SNDSLOTS	;SEE IF DONE WITH LIST
	BCC	S30			;DO NEXT
S50:	LDA	#0
	RTS


PLAYING:
	JSR	SNDINDX		;IN RANGE?
	BNE	PL10
	LDA	SND_RAM+SF,X	;IN USE?
	BMI	PL20
	LDA	#0
PL10:	RTS
PL20:	LDA	#1		;IF IT IS, RETURN 1
	RTS


INITBACK:
	JSR	ALLOW_WRITES

	STX	WORLDPTR
	STY	WORLDPTR+1
	JSR	SIZE_LIST	;MAKE THE PARAMETERS ABOUT THIS BACKGROUND.
	LDA	#-1
	STA	BACKVALID	;ENABLE BACKGROUND SCROLL CREATION

	JSR	WRITE_SCNBUF	;CLEAR THE BUFFER WE NEED
	JSR	FIXSCROLL	;FIX THE USER'S WINDOW VALUES
	JSR	MAKECOL		;MAKE THE ROW AND COLUMN OF UPPER LEFT SCREEN		


	LDX	#33		;GET LOOP COUNT
	LDA	WORLD_WIDTH+1	;SEE IF WORLD CAN TAKE IT
	BNE	IB50
	CPX	WORLD_WIDTH
	BCC	IB50
	LDX	WORLD_WIDTH	;IF WORLD SMALLER THAN 33, USE MAX

IB50: 	TXA
	PHA

	JSR	FINDCOL		;FIND OUT WHERE THE NEXT COLUMN IS STORED
	JSR	BUILD_COL	;GET DATA ROW INTO SCNBUF. 
	JSR	WRITE_SCNBUF

	LDA	FETCHCOL
	CLC
	ADC	#1
	STA	FETCHCOL
	BCC	IB66
	INC	FETCHCOL+1	;MOVE TO NEXT COLUMN

IB66: 	PLA
	TAX
	DEX
	BNE	IB50		;DO ALL 33 COLS


	LDA	XBACK
	STA	CURX
	LDA	XBACK+1
	STA	CURX+1

	LDA	YBACK
	STA	CURY
	LDA	YBACK+1
	STA	CURY+1		;SET WINDOW AS CURRENT LOCATION

	JSR	MAKE_SCROLL	;CONVERT IT INTO SCROLL VALUES


	LDA	WORLDSPOT
	STA	XWORLDSPOT

	LDA	WORLDSPOT+1
	STA	XWORLDSPOT+1

	LDA	SPOTCOL
	STA	XSPOTCOL

	LDA	SPOTCOL+1
	STA	XSPOTCOL+1

	LDA	BACKBASE
	STA	XBACKBASE

	LDA	BACKBASE+1
	STA	XBACKBASE+1

	LDA	BPBASE
	STA	XBPBASE

	LDA	BPBASE+1
	STA	XBPBASE+1

	LDA	BACKSIZE
	STA	XBACKSIZE

	LDA	BACKWIDE
	STA	XBACKWIDE

	LDA	BACKHIGH
	STA	XBACKHIGH

	LDA	BPWIDE
	STA	XBPWIDE


RESUME_NMI:			
	LDA	REG2000
	ORA	#H'80
	STA	H'2000		;REENABLE NMI AND LET IT REENABLE VIDEO
	RTS


ALLOW_WRITES:
	JSR	STOP_NMI	;DISABLE NMI
	JSR	VERT_WAIT	;WAIT TO PREVENT SCREEN FLASH
	LDA	#6
	STA	H'2001		;ENABLE SCREEN WRITES, DISABLE VIDEO
	RTS

MAKECOL:
	LDX	XBACK
	LDY	XBACK+1
	JSR	ADJ_BACK
	STY	FETCHCOL+1
	STX	FETCHCOL

	LDX	YBACK
	LDY	YBACK+1
	JSR	ADJ_BACK
	STX	FETCHROW	;MAKE /8 ROW (BYTE)
	RTS


SIZE_LIST:

IFDEF( `BLOCKMODE', `		

	LDA	WORLDPTR
	STA	SUBSVAR1
	LDA	WORLDPTR+1
	STA	SUBSVAR2
	JSR	GETWORD		;GET WIDTH AND HEIGHT OF BLOCK

	LDA	SUBSVAR1	;GET WIDTH IN BLOCKS OF WORLD
	STA	BLOCK_WIDTH	;SAVE HERE
	TAY
	LDX	#8
	JSR	MUL
	STX	WORLD_WIDTH
	STY	WORLD_WIDTH+1	;SET RESULTING LENGTH

	TXA			;GET LOW BYTE OF RESULTING LENGTH
	SEC
	SBC	#32
	STA	END_COL
	STA	RIGHTLIMIT
	TYA
	SBC	#0
	STA	END_COL+1
	STA	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1	;MAKE END PIXEL VALUE

	LDA	SUBSVAR2		;GET HEIGHT IN BLOCKS
	TAY
	LDX	#8
	JSR	MUL		;MAKE HEIGHT IN ROWS
	STX	WORLD_HEIGHT	;SAVE HEIGHT OF WORLD IN ROWS
	TXA			;WILL BE LESS THAN 256
	SEC
	SBC	#30		;MAKE LAST ROW FOR SCREEN.
	BCS	SLZ10
	LDA	#0		;IF ITS 0, SET AS SUCH
SLZ10:	STA	END_ROW
	STA	BOTLIMIT
	LDA	#0
	STA	BOTLIMIT+1
	ASL	BOTLIMIT
	ROL	BOTLIMIT+1
	ASL	BOTLIMIT
	ROL	BOTLIMIT+1
	ASL	BOTLIMIT
	ROL	BOTLIMIT+1	;MAKE END PIXEL VALUE

	LDA	WORLDPTR
	CLC
	ADC	#2		;POINT DIRECTLY TO THE FIRST ENTRY
	STA	WORLDPTR
	LDA	WORLDPTR+1
	ADC	#0
	STA	WORLDPTR+1
	RTS

	', `


	LDA	WORLDPTR
	STA	WORLDSPOT
	LDA	WORLDPTR+1
	STA	WORLDSPOT+1	;SET UP A POINTER
	LDA	#0		;MAKE AN INDEX TO USE
	STA	WORLD_WIDTH
	STA	WORLD_WIDTH+1	;ZERO WIDTH IN COLUMNS
	
SLZ10: 	LDY	#1
	LDA	(WORLDSPOT),Y	;GET UPPER BYTE OF BACKGROUND NAME
	CMP	#-1
	BEQ	SLZ50
	JSR	POINTBACK	;GET BACKGROUND SIZE
	LDA	BACKWIDE
	CLC
	ADC	WORLD_WIDTH
	STA	WORLD_WIDTH
	BCC	SLZ30
	INC	WORLD_WIDTH+1

SLZ30:	JSR	NEXTSPOT	;MOVE TO NEXT ENTRY IN WORLD LIST
	JMP	SLZ10


SLZ50:	LDA	WORLDPTR
	STA	WORLDSPOT
	LDA	WORLDPTR+1
	STA	WORLDSPOT+1	;RETURN WORLDSPOT=WORLDPTR
	LDA	#0
	STA	SPOTCOL		;SET WHAT WORLDSPOT POINTS TO
	STA	SPOTCOL+1
	JSR	POINTBACK	;AND MAKE INFO VALID FOR THAT BACKGROUND

	LDA	WORLD_WIDTH	;GET FINAL WIDTH	
	SEC
	SBC	#32
	STA	END_COL
	LDA	WORLD_WIDTH+1
	SBC	#0
	STA	END_COL+1
	LDA	END_COL
	STA	RIGHTLIMIT
	LDA	END_COL+1
	STA	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1
	ASL	RIGHTLIMIT
	ROL	RIGHTLIMIT+1	;MAKE END PIXEL VALUE

	LDA	BACKHIGH	
	STA	WORLD_HEIGHT	;SET HEIGHT OF WORLD SAME AS FIRST STRIP

	RTS

	' )


NEXTSPOT:
	LDA	WORLDSPOT
	CLC
	ADC	#2
	STA	WORLDSPOT
	BCC	NXP10
	INC	WORLDSPOT+1	;MOVE INDEX TO NEXT LIST ENTRY
NXP10:	RTS


PREVSPOT:
	LDA	WORLDSPOT
	SEC
	SBC	#2
	STA	WORLDSPOT
	BCS	PVR10
	DEC	WORLDSPOT+1	;MOVE INDEX TO NEXT LIST ENTRY
PVR10:	RTS


GETWORD:
	LDA	SUBSVAR3
	PHA
	PHA
	PHA			;MOVE STACK DOWN 3
	LDA	#2
	STA	SUBSVAR3
	JSR	FILLSTACK	;GET THE BYTES WE WANTED
	TSX
	LDA	257,X
	STA	SUBSVAR1
	LDA	258,X
	STA	SUBSVAR2
	PLA
	PLA
	PLA			;FIX STACK
	STA	SUBSVAR3
	RTS


FINDCOL:

IFDEF( `BLOCKMODE', `

	LDA	FETCHCOL
	STA	WORLDSPOT
	LDA	FETCHCOL+1
	LSR	A
	ROR	WORLDSPOT
	LSR	A
	ROR	WORLDSPOT
	LSR	A
	ROR	WORLDSPOT	;MAKE BLOCK NUMBER COLUMN ITS ON

	LDA	FETCHROW
	LSR	A
	LSR	A
	LSR	A		;MAKE BLOCK NUMBER ROW ITS IN BACKGRND MATRIX
	TAX
	LDY	BLOCK_WIDTH
	JSR	MUL		;MAKE BLOCK NUMBER OF START OF THIS ROW
	LDA	WORLDSPOT
	JSR	ADD_WORD
	STX	WORLDSPOT
	STY	WORLDSPOT+1	;SET INITIAL BLOCK NUMBER

IFDEF( `INDIRECT', `
				;IF INDIRECT MODE, 1 BYTE PER BACKGROUND
	', `
	ASL	WORLDSPOT
	ROL	WORLDSPOT+1	;IF NOT INDIRECT MODE,DOUBLE EACH FOR WORD
	' )

	LDA	WORLDSPOT
	CLC
	ADC	WORLDPTR	;ADD OFFSET OF ACTUAL MATRIX
	STA	WORLDSPOT
	LDA	WORLDPTR+1
	ADC	WORLDSPOT+1
	STA	WORLDSPOT+1	;MAKE DIRECT POINTER TO THE BLOCK WE MUST USE
	LDA	FETCHCOL
	AND	#7		;MAKE COLUMN WITHIN BACKGROUND
	STA	SUBSVAR6
	JMP	POINTBACK	;SET UP BACKBASE, ETC
	', ` 

	LDA	FETCHCOL
	SEC
	SBC	SPOTCOL
	STA	SUBSVAR6
	LDA	FETCHCOL+1
	SBC	SPOTCOL+1	;MAKE DISTANCE TO THIS COLUMN
	BCS	FC20


	JSR	PREVSPOT	;BACK UP THE POINTER
	JSR	POINTBACK	;SET UP FOR THIS ONE
	LDA	SPOTCOL
	SEC
	SBC	BACKWIDE	;CORRECT FOR WIDTH
	STA	SPOTCOL
	BCS	FC15
     	DEC	SPOTCOL+1
FC15:	JMP	FINDCOL		;AND TRY AGAIN.		


FC20:	CMP	#0		;MAKE SURE NOT OUT OF RANGE
	BNE	FC40
	LDA	SUBSVAR6
	CMP	BACKWIDE	;IN RANGE?
	BCC	FC50


FC40:	JSR	NEXTSPOT
	LDA	SPOTCOL
	CLC
	ADC	BACKWIDE	;CORRECT FOR WIDTH
	STA	SPOTCOL
	BCC	FC45
     	INC	SPOTCOL+1
FC45:	JSR	POINTBACK
	JMP	FINDCOL

FC50:	RTS
	 ' )


POINTBACK:
IFDEF( `BLOCKMODE', `


	LDA	SUBSVAR1
	PHA
	LDA	SUBSVAR2
	PHA

	LDA	WORLDSPOT
	STA	SUBSVAR1
	LDA	WORLDSPOT+1
	STA	SUBSVAR2
	JSR	GETWORD		;GET THE 1 WORD BLOCK PTR OR 1 BYTE BLOCK #.

	LDY	#0
IFDEF( `INDIRECT', `
	LDA	SUBSVAR1	;ITS INDIRECT MODE.  THIS IS INDEX TO BACKGRND
	STA	BACKBASE
	STY	BACKBASE+1
	ASL	BACKBASE
	ROL	BACKBASE+1	;MAKE *2 POINTER FROM BLOCK NUMBER
	LDA	#BLOCKS & 255
	CLC
	ADC	BACKBASE
	STA	BACKBASE
	LDA	#BLOCKS >> 8
	ADC	BACKBASE+1
	STA	BACKBASE+1
	LDA	(BACKBASE),Y
	PHA
	INY
	LDA	(BACKBASE),Y
	STA	BACKBASE+1
	PLA
	STA	BACKBASE
	', `
	LDA	SUBSVAR1	;IF DIRECT BLOCK MODE, (WORLDSPOT) HAS ADDRESS
	STA	BACKBASE
	LDA	SUBSVAR2
	STA	BACKBASE+1
	' )
	LDA	#8
	STA	BACKWIDE
	STA	BACKHIGH
	LDA	BACKBASE
	CLC
	ADC	#64		;SKIP TO PALETTE DATA
	STA	BPBASE
	LDA	BPBASE+1
	ADC	#0
	STA	BPBASE+1

	PLA
	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1

	RTS

	', ` 


	LDY	#0
	LDA	(WORLDSPOT),Y
	STA	BACKBASE
	STA	SUBSVAR1
	INY
	LDA	(WORLDSPOT),Y
	STA	BACKBASE+1	;GET NEXT BACKGROUND
	STA	SUBSVAR2

	TSX
	TXA
	SEC
	SBC	#4
	TAX
	TXS
	LDA	#3
	STA	SUBSVAR3
	JSR	FILLSTACK	;GET THE BACKGROUND HEADER
	TSX
	INX			;POINT TO THE DATA

	LDA	256,X
	STA	BACKSIZE
	LDA	257,X
	STA	BACKWIDE
	CLC
	ADC	#3		;ROUND WIDTH UP TO MAKE PALETTE WIDTH
	ROR	A
	LSR	A		;AND DIVIDE BY 4 TO GET PALETTE WIDTH
	STA	BPWIDE
	LDA	258,X
	STA	BACKHIGH	;GET THE 3 BACKGROUND PARAMETERS

	TXA
	CLC
	ADC	#3
	TAX
	TXS			;FIX THE STACK

	LDA	BACKBASE
	CLC
	ADC	#3
	STA	BACKBASE
	LDA	BACKBASE+1
	ADC	#0
	STA	BACKBASE+1	;MAKE POINTER POINT TO THE ACTUAL DATA ROWS

	LDX	BACKWIDE
	LDY	BACKHIGH
	JSR	MUL		;MAKE A POINTER TO THE PALETTE INFO
	CLC
	TXA
	ADC	BACKBASE
	STA	BPBASE
	TYA
	ADC	BACKBASE+1
	STA	BPBASE+1	;POINT DIRECTLY TO IT IN MEMORY
	RTS
	 ' )


SCRLX:				;CALL HERE TO SCROLL X ONLY
	LDA	#1			
SCRL5:	LDX	BACKVALID
	BEQ	SCRL10
	ORA	MOVEBACK
	STA	MOVEBACK		;JUST SET A FLAG
SCRL10:	RTS

IFDEF( `BLOCKMODE', `		;BLOCK MODE HAS A Y STARTING OFFSET
SCRLY:				;CALL HERE TO SCROLL Y ONLY.
	LDA	#2		;SET Y SCROLL BIT
	JMP	SCRL5
	', )


BACKPAL:
	STX	BPAL_BASE
	STY	BPAL_BASE+1	;SET BASE OF PALETTE INFO
	LDA	#1
	JMP	SPL10


SPRITEPAL:
	STX	SPAL_BASE
	STY	SPAL_BASE+1	;SET BASE OF PALETTE INFO
	LDA	#2
SPL10:	ORA	NEW_PAL
	STA	NEW_PAL		;SET FLAG TO INIT PALETTE DURING NMI
	RTS


ROTATE:
	LDA	BASESPRITE	;ROTATION OFF IS IGNORED UNTIL BASE=0
	BNE	RTT0
	LDA	ROTATEFLG	;OFF?
	BEQ	RTT1
	LDA	TOOMANY		;SEE IF SUBS FOUND TOO MANY ON LINE
	BNE	RTT0
RTT1:	JMP	RTT100


RTT0:  	LDA	#-1
	STA	ROTATING	;LOCK OUT ANY SPRITE DMA TRANSFERS
	TSX
	TXA
	SEC
	SBC	#H'20		;MAKE ROOM TO SAVE 32 BYTES ON STACK
	TAX
	TXS
	INX			;POINT TO PLACE TO SAVE THEM
	STX	SUBSVAR2	;SAVE LOCATION IN STACK MEMORY
	LDA	BASESPRITE	;NOW MAKE THE COUNT TO ROTATE THEM BY
	BEQ	RTT4
	CMP	#H'20
	BCC	RTT5		;WE ROTATE BY H'20 TILL WE GET CLOSE TO 0.
RTT4:	LDA	#H'20		;THEN WE ROTATE BY H'1C TO RESTORE 0 BASE.
RTT5:	STA	SUBSVAR1	;MAKE COUNTER
	STA	SUBSVAR3	;AND SAVE THE ADJUSTMENT TO BASESPRITE

	LDY	#0
RTT10:	LDA	SPRAM,Y
	STA	H'100,X
	INY
	INX
	DEC	SUBSVAR1
	BNE	RTT10		;SAVE THE FIRST 32 FOR OVERLAPPING MOVE


	LDX	#0
	LDA	#H'FC
	SEC
	SBC	SUBSVAR3	;MAKE AMOUNT TO BE MOVED DOWN
	STA	SUBSVAR1	;WHICH DEPENDS ON WHAT OUR ADJUSTMENT WAS
RTT20:	LDA	SPRAM,Y
	STA	SPRAM,X
	INY
	INX
	DEC	SUBSVAR1
	BNE	RTT20


	LDA	SUBSVAR3	;GET COUNT WE PUT INTO THE STACK
	STA	SUBSVAR1
	LDY	SUBSVAR2

RTT30:	LDA	H'100,Y
	STA	SPRAM,X
	INY
	INX
	DEC	SUBSVAR1
	BNE	RTT30
	

	LDA	#SPSLOTS
	STA	SUBSVAR1	;SET COUNT OF SPRITE SLOTS TO CHANGE
	LDX	#0		;POINT TO FIRST
	
RTT40:	LDA	ANIM_RAM+BS,X	;GET BASE SPRITE
	SEC
	SBC	SUBSVAR3	;CORRECT IT
	BCS	RTT45
	SEC
	SBC	#4		;AND SKIP LAST SPRITE

RTT45:	STA	ANIM_RAM+BS,X
	TXA
	CLC
	ADC	#ANIM_WIDE	;MOVE TO NEXT SLOT
	TAX
	DEC	SUBSVAR1
	BNE	RTT40	

	LDA	BASESPRITE
	SEC
	SBC	SUBSVAR3
	BCS	RTT50
	SEC
	SBC	#4
RTT50:	STA	BASESPRITE	;SET NEW BASE SPRITE
	TSX
	TXA
	CLC
	ADC	#H'20		;FIX THE STACK
	TAX
	TXS
RTT100:	LDA	#0
	STA	ROTATING	;ALLOW SPRITE DMA TRANSFERS
	RTS
	

INITSPRT:

	STX	SUBSVAR1
	STY	SUBSVAR2

	JSR	ANIMINDX
	BEQ	II20
	RTS			;IF BAD INDEX, RETURN TO CALLER.

II20:
	LDA	ANIM_RAM+FB,X	;GET THE ANIMATION FLAG
	BEQ	II30		;IF FREE, OK TO CONTINUE
	LDA	#1		;IF NOT FREE, RETURN 1.
	RTS

II30:  	LDA	SUBSVAR1
	STA	ANIM_RAM+PTRL,X
	LDA	SUBSVAR2       	;GET BACK INDEXES
	STA	ANIM_RAM+PTRH,X	;PUT MEMORY LOCATION INTO STRUCTURE

	LDA	ANIM_RAM+AF,X	;GET CURRENT AUX FLAGS
	AND	#H'C0		;KEEP OLD DIRECTION BITS
	STA	ANIM_RAM+AF,X	;ZERO OTHER BITS IN THE AUX FLAGS
	

	LDY	#0
	LDA	(SUBSVAR1),Y	;GET THE FLAG BYTE
	CMP	#79		;ASCII "O"?
	BNE	II90
	LDA	#0		;NOT SUPPORTED
	RTS

II90:	CMP	#83		;ASCII "S"
	BEQ	II100		;IF IT IS, GO TO INIT THAT


	LDA	#H'C1
	STA	ANIM_RAM+BS,X	;SET AS SIMPLE SPRITE BLOCK, BUT FROZEN
	JMP	II120		;GO SHARE ENDING CODE WITH ANIMATION SETUP.
	

II100:	LDA	#H'82
	STA	ANIM_RAM+BS,X	;SET AS SPRITE ANIMATION
	LDA	#0
	STA	ANIM_RAM+FR,X	;ZERO THE FRAME WE ARE CURRENTLY DISPLAYING
	LDY	#2
	LDA	(SUBSVAR1),Y	;GET THE FREQUENCY
	STA	ANIM_RAM+CN,X	;SET INITIAL FREQUENCY
	STA	ANIM_RAM+RL,X	;AND SET RELOAD VALUE
	INY
	LDA	(SUBSVAR1),Y
	INY
	PHA
	LDA	(SUBSVAR1),Y	;GET FIRST ENTRY'S POINTER
	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1	;SET OFFSET FOR SHARED INIT OF FIRST FRAME


II120: 	LDA	ANIM_RAM+PA,X	;GET THE PREALLOCATE VALUE
	STA	ALLOCATION	;SET FOR OUR LOOP ALLOCATE
	TXA

	PHA			;SAVE THE SLOT INDEX
	LDY	#1
	LDA	(SUBSVAR1),Y	;GET WIDTH

IFDEF( `COMPRESS_SPRITES', `
	LSR	A
	LSR	A
	LSR	A
	LSR	A		;shift it down to low nybble
	', `
	INY
	')

	TAX
	LDA	(SUBSVAR1),Y	;GET HEIGHT

IFDEF( `COMPRESS_SPRITES', `
	AND	#15		;get low nybble only
	', )

	TAY
	JSR	MUL		;MAKE NUMBER OF SPRITES USED
	STX	MATH2		;SAVE HERE

	LDY	#0
	LDA	(SUBSVAR1),Y	;GET RECOMMENDED BASE SPRITE
	AND	#H'7F
	ASL	A
	ASL	A		;MAKE #4 POINTER TO THE BLOCK
	CLC
	ADC	BASESPRITE	;ADJUST FOR CURRENT BASE SPRITE
	BCS	II122
	CMP	#252
	BNE	II121

II122:	CLC
	ADC	#4		;IF WE WRAP, SKIP LAST SPRITE

II121:	STA	MATH1
	TAY



II130: 	LDX	ALLOCATION	;SEE IF PREALLOCATION AMOUNT
	BNE	II131
	LDX	MATH2		;GET COUNT TO BE FOUND
II131:	STY	SUBSVAR3	;SAVE INDEX WE WERE CHECKING.

II140:	LDA	SPRAM+2,Y	;GET IN USE FLAG
	STA	SUBSVAR4	;SAVE IN USE FLAG
II141:	INY
	INY
	INY	
	INY			;SKIP THIS SPRITE
	CPY	#252		;WRAP INDEX AT LAST SPRITE
	BEQ	II141		;BUT SPRITE #0 IS DEDICATED TO TOP STAT BAR
	TYA
	EOR	MATH1		;REACHED LIST END?
	BEQ	II145		;IF SO, DIDN'T FIND THE COUNT WE NEEDED.
	LDA	SUBSVAR4	;GET BACK THE IN USE FLAG
	AND	#8		;IN USE?
	BNE	II130		;IF IN USE, MUST SKIP THIS ONE
	DEX
	BNE	II140	
	JMP	II160

II145:	PLA			;DISCARD SLOT #
	LDA	#2		;IF END OF SPRITES AND NOT ENOUGH, RETURN ERR
	RTS

II160:	LDY	SUBSVAR3	;GET BACK BASE SPRITE WE CAN USE
	PLA
	TAX			;GET BACK SLOT INDEX
	LDA	MATH2		;GET BACK NUMBER OF SPRITES USED
	STA	ANIM_RAM+NS,X	;SET INTO STRUCTURE

	LDA	ANIM_RAM+BS,X	;GET FLAG TYPE WE PUT HERE FOR TEMP USAGE
	STA	SUBSVAR3	;SAVE IT
	TYA
	STA	ANIM_RAM+BS,X	;SAVE SPRITE BASE INDEX IN STRUCTURE


	LDA	ALLOCATION
	BEQ	II170

	LDA	#8		;MAKE AN ALLOCATION FLAG
II165:	STA	SPRAM+2,Y	;SET IN USE FLAG
II166:	INY
	INY
	INY	
	INY			;SKIP THIS SPRITE
	CPY	#252		;WRAP INDEX AT LAST SPRITE
	BEQ	II166		;BUT SPRITE #0 IS DEDICATED TO TOP STAT BAR
	DEC	ALLOCATION	;LOWER ALLOCATION COUNT
	BNE	II165	


II170:	LDA	REG2000	
	AND	#H'DF		;ASSUME NOT DOUBLING SPRITE
	LDY	#0		
	PHA
	LDA	(SUBSVAR1),Y	;GET FLAG FROM THE SPRITE STRUCTURE
	ASL	A
	PLA
	BCC	II180
	ORA	#H'20
II180:	STA	REG2000		;SET CONDITION OF SPRITE DOUBLE
	AND	#H'20
	STA	DOUBLE_BIT	;AND KEEP A COPY OF IT.


	LDA	SUBSVAR3
	STA	ANIM_RAM+FB,X


	JSR	SPFRAME		

	LDA	#0
	RTS


PUTSPRT:
	STX	SUBSVAR3
	STY	SUBSVAR4	;SAVE DESIRED X AND Y LOCATION
	JSR	ANIMINDX	;SEE IF VALID SLOT NUMBER
	BEQ	PU20
	RTS

PU20:  	LDA	ANIM_RAM+PTRL,X	
	STA	SUBSVAR1
	LDA	ANIM_RAM+PTRH,X
	STA	SUBSVAR2	;ASSUME DIRECT POINTER STORED IN SPRITE SLOT
	LDA	ANIM_RAM+FB,X	;GET TYPE OF STRUCTURE
	AND	#H'7F		;REMOVE NOT POSITIONED BIT
	STA	ANIM_RAM+FB,X	;PUT BACK
	AND	#3
	BEQ	PU25		;IF NOT IN USE, BAD TYPE
	CMP	#3		;SEE IF OBJECT OR SPRITE
	BNE	PU21
	LDA	#0		;NOT SUPPORTED
	RTS		

PU21:	CMP	#1
	BEQ	PU30		;IF JUST SPRITE, OUR PTR IS GOOD
	LDY	#1
	LDA	(SUBSVAR1),Y	;ASSUME SPRITE ANIMATION, GET FRAMES IN CASE
	STA	SUBSVAR5	;OF UPDATE BY SCREEN ALIGNMENT
	LDY	#3		;OTHERWISE WE NEED TO GET A NEW PTR
	LDA	(SUBSVAR1),Y
	PHA
	INY
	LDA	(SUBSVAR1),Y
	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1	;USE FIRST FRAME OF ANIMATION AS INFO PTR
	JMP	PU30

PU25:	LDA	#1		;NOT IN USE OR UNKNOWN TYPE.
	RTS


PU30: 	LDA	SUBSVAR4	;GET SPRITE LOCATION
	CLC
	ADC	SPYADJ		;ADJUST Y ACCORDING TO USER REQUEST
	STA	SUBSVAR4	;AND PUT BACK FOR OUR USE

	LDY	#0
	LDA	(SUBSVAR1),Y	;GET FLAG OF 1 OR 2 HIGH SPRITES
	PHA			;SAVE IT
	INY
	LDA	(SUBSVAR1),Y	;GET WIDTH

IFDEF( `COMPRESS_SPRITES', `
	LSR	A
	LSR	A
	LSR	A
	LSR	A		;Shift it down to low nybble
	', `
	INY
	')

	PHA
	LDA	(SUBSVAR1),Y	;GET HEIGHT

IFDEF( `COMPRESS_SPRITES', `
	AND	#15		;Get low nybble only
	', )

	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1	;SAVE BOTH

 	LDY	ANIM_RAM+BS,X	;GET BASE SPRITE INDEX
	LDA	#8		;ASSUME 1 HIGH
	STA	MATH1
	PLA			;GET FLAG OF 1 OR 2 HIGH
	BPL	PU50
	LDA	#16
	STA	MATH1		;IF 2 HIGH, USE 16 AS CORRECTION.	


PU50: 	LDA	SUBSVAR1	;GET WIDTH
	STA	MATH2		;SAVE HERE FOR LOOP COUNT
	LDA	SUBSVAR3
	PHA			;SAVE STARTING X LOCATION FOR LOOP
	
PU55: 	LDA	SUBSVAR4	;GET Y LOCATION
	STA	SPRAM,Y		;SET CURRENT Y LOC
	LDA	SUBSVAR3
	STA	SPRAM+3,Y	;AND SET X TOO

	CLC
	ADC	#8		;MOVE RIGHT 8
	BCC	PU60
	LDA	#H'FF		;WENT PAST END, FIX IT.
PU60:	STA	SUBSVAR3  	;PUT BACK CORRECTED X
PU61:	INY
	INY	
	INY
	INY
	CPY	#252		;WRAP INDEX AT LAST SPRITE
	BEQ	PU61
	DEC	MATH2		;COUNT 1 LESS ON THIS ROW
	BNE	PU55		;DO ALL OF THEM
	PLA
	STA	SUBSVAR3	;RESTORE START OF ROW X
	LDA	SUBSVAR4	;GET Y LOCATION
	CLC
	ADC	MATH1		;CORRECT Y FOR NEXT ROW ACCORDING TO HEIGHT
	BCS	PU70
	CMP	#H'F9
	BCC	PU75
PU70:	LDA	#H'F8		;BOTTOM IS F8
PU75:	STA	SUBSVAR4
	DEC	SUBSVAR2	;COUNT 1 LESS ROW
	BNE	PU50


PU77:	LDA	ANIM_RAM+FB,X	;GET BACK THE FLAG
	AND	#H'70		;KEEP FROZEN AND ALIGNMENT BITS
	BEQ	PU90 		;IF NONE, NO NEED TO WORRY
	CMP	#H'40		;BUT FROZEN?
	BCS	PU90		;IF SO, DONT UPDATE BY ANY METHOD BUT SELFRAME


	LDA	ANIM_RAM+FB,X
	AND	#3
	CMP	#1		;MAKE SURE NO ERROR (SPRITE BLOCK DOESN'T MOVE)
	BEQ	PU90
		
	LDA	ANIM_RAM+FB,X	;GET BACK X ALIGN BIT (20H)
	ROL	A
	ROL	A
	ROL	A		;GET X BIT INTO CY

	LDY	ANIM_RAM+BS,X
	LDA	YBACK		;CURY
	STA	SUBSVAR3

PU78:	LDA	SPRAM,Y		;ASSUME UPDATE BY Y
	BCC	PU80
PU79:	LDA	XBACK		;CURX
	STA	SUBSVAR3
	LDA	SPRAM+3,Y	;IF BY X, GET X

PU80: 	CLC
	ADC	SUBSVAR3
	STA	SUBSVAR3	;SAVE THE LOCATION TO USE
	LDA	ANIM_RAM+AF,X	;GET SHIFT COUNT
	AND	#H'07
	TAY
	INY
PU82:	DEY
	BEQ	PU83
	LSR	SUBSVAR3	;SHIFT LOCATION DOWN BY REQUESTED AMOUNT
	JMP	PU82

PU83:  	STX	SUBSVAR4	;SAVE INDEX
	LDX	SUBSVAR3	;GET FRAME TO USE
	LDY	#0
	LDA	SUBSVAR5	;GET NUMBER OF FRAMES
	JSR	DIVIDE		;QUICKER TO DIVIDE THAN SUBTRACT ON AVERAGE


  	LDX	SUBSVAR4	;GET BACK INDEX
	LDA	ANIM_RAM+FB,X	;GET BACK X ALIGN BIT (20H)
	AND	#H'20
	BEQ	PU85		;IF BY Y, MIRROR DOESN'T MATTER.

	LDA	ANIM_RAM+AF,X	;SEE IF MIRRORED SPRITE
	AND	#H'40
	BEQ	PU85
	LDA	SUBSVAR5	;GET BACK NUMBER OF FRAMES IF SO
	STY	SUBSVAR5
	CLC
	SBC	SUBSVAR5	;MAKE BACKWARDS SELECTION IF MIRRORED
	TAY		

PU85:  	TYA			;GET REMAINDER AS FRAME TO USE
	LDY	ANIM_RAM+FR,X	;GET CURRENT FRAME
	STA	ANIM_RAM+FR,X	;SET CURRENT FRAME
	TYA
	EOR	ANIM_RAM+FR,X	;SEE IF FRAME HAS CHANGED
	BEQ	PU90		;IF NO CHANGE, DON'T WASTE TIME UPDATING.
	JSR	SPFRAME

PU90:	LDA	#0		;SIGNAL SUCCESS
	RTS			



TESTPUT:
	STX	TESTX
	STY	TESTY		;SAVE THE LOCATION

	JSR	USEDINDX	;CHECK OUT THE SLOT, RETURN FROM THERE IF BAD
	STX	SUBSVAR5	;SET SLOT
	AND	#8		;SOLID DEFINED?		
	BNE	CS04
	LDA	#0		;RETURN OK FLAG
	RTS

CS04: 	LDA	TESTX		;GET X LOCATION
	STA	MATH1		;SAVE DESIRED NEW X LOCATION
	LDA	TESTY		;GET DESIRED Y CORRECTION
	STA	MATH4		;SAVE DESIRED NEW Y LOCATION.


	LDA	MATH1		;GET DESIRED X LOCATION
	CLC
	ADC	XBACK		;MAKE OFFSET IN BACKGROUND
	STA	FETCHCOL
	LDA	XBACK+1		
	ADC	#0
	STA	FETCHCOL+1	;FETCHCOL HAS X PIXEL LOC IN BACKGROUND


	LDA	ANIM_RAM+PTRL,X
	STA	SUBSVAR1
	LDA	ANIM_RAM+PTRH,X
	STA	SUBSVAR2	;MAKE (SUBSVAR1) POINT TO THE ANIMATION/SPRITE

	LDA	ANIM_RAM+FB,X
	AND	#3
	CMP	#1		;JUST A SPRITE?
	BEQ	CS30		;IF IT IS, PTR IS TO A BLOCK WITH WIDTH/HEIGHT
	LDY	#3
	LDA	(SUBSVAR1),Y
	PHA
	INY
	LDA	(SUBSVAR1),Y
	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1	;IF ANIMATION, NEED POINTER TO BLOCK

CS30:	LDY	#1
	LDA	(SUBSVAR1),Y	;GET WIDTH

IFDEF( `COMPRESS_SPRITES', `
	LSR	A
	LSR	A
	LSR	A
	LSR	A		;Shift it down to low nybble
	', )

	STA	MATH1		;SAVE HERE
	DEC	MATH1		;COUNT 1 LESS ON WIDTH (4 PIXELS OFF EACH SIDE)
	BNE	CS31
	INC	MATH1		;IF ONLY 1 WIDE, CAN'T DO IT
	JMP	CS31A

CS31: 	LDA	FETCHCOL	;IF MORE THAN 1 WIDE, WE CAN IGNORE 4 ON LEFT
	CLC
	ADC	#4		;MOVE RIGHT TO IGNORE 4 ON LEFT 
	STA	FETCHCOL
	LDA	FETCHCOL+1
	ADC	#0
	STA	FETCHCOL+1	;AND COUNT 4 LESS PIXELS ON LEFT.

CS31A:

IFDEF( `COMPRESS_SPRITES', , `
	INY
	')

	LDA	(SUBSVAR1),Y	;GET HEIGHT

IFDEF( `COMPRESS_SPRITES', `
	AND	#15		;Get low nybble only
	', )

	STA	MATH2		;SAVE HEIGHT
	LDY	#0
	LDA	(SUBSVAR1),Y	;SEE IF 2 HIGH SPRITE
	BPL	CS35
	ASL	MATH2		;IF 2 HIGH, DOUBLE HEIGHT

CS35:	LDA	MATH2		;GET BACK HEIGHT IN CHARACTERS
	JSR	TIMES8		;MULTIPLY BY 8
	DEC	MATH4		;NEED TO COME UP TO BOTTOM PIXEL OF FEET
	CLC
	ADC	MATH4
	CLC
	ADC	YBACK		;MAKE OFFSET IN BACKGROUND
	STA	MATH4
	LDA	#0
	ADC	YBACK+1

	LSR	A
	ROR	MATH4
	LSR	A
	ROR	MATH4
	LSR	A		;MAKE TEXT ROW OF BOTTOM SPRITE
	ROR	MATH4
	LDA	MATH4
	STA	FETCHROW	;SAVE FOR FINDCOL

	LSR	FETCHCOL+1	;NOW FIX THE COLUMN TO FETCH.  WAS STILL IN
	ROR	FETCHCOL	;PIXELS TO SEE IF WE NEEDED TO ADD 4.
	ROR	SUBSVAR4
	LSR	FETCHCOL+1
	ROR	FETCHCOL
	ROR	SUBSVAR4
	LSR	FETCHCOL+1
	ROR	FETCHCOL	;MAKE FETCHCOL=TEXT COL,
	ROR	SUBSVAR4	;SUBSVAR4=ODD PIXELS

	CMP	WORLD_HEIGHT	;MAKE SURE CHECK ROW IS IN RANGE
	BCC	CS37	


IFDEF( `SOLFILL', `		
	LDA	#-1		;THIS MAKES DATA BELOW BACKGROUND BE SOLID
 	STA	SOLIDCHAR	
	LDA	#4
	RTS
	', `			
	LDA	#0		;THIS MAKES DATA BELOW BACKGROUND BE EMPTY
	RTS
	')

PAST_RIGHT:
	LDA	WORLD_WIDTH
	SEC
	SBC	#1
	STA	FETCHCOL
	LDA	WORLD_WIDTH+1
	SBC	#0
	STA	FETCHCOL+1	;IF PAST RIGHT ON CHECK, CHECK LAST COL ONLY
	LDA	#1
	STA	SUBSVAR4
	JMP	CS50B

CS37:	LDA	SUBSVAR4	;GET ODD PIXELS ON COL
	AND	#B'11100000
	BEQ	CS50
	INC	MATH1		;IF THERE ARE SOME, NEED EXTRA COL CHECK

CS50:	LDA	MATH1
	STA	SUBSVAR4	;PUT COLS TO CHECK HERE
	
	LDA	WORLD_WIDTH
	SEC
	SBC	FETCHCOL
	TAY
	LDA	WORLD_WIDTH+1
	SBC	FETCHCOL+1	;FIND OUT HOW MANY REMAIN IN THIS WORLD
	BCC	PAST_RIGHT
	BNE	CS50B		;IF >256 ITS OK
	CPY	SUBSVAR4	;SEE IF WE ARE CHECKING TOO MANY
	BEQ	CS50A
	BCS	CS50B
CS50A:	STY	SUBSVAR4	;IF SO, LOWER WIDTH OF CHECK
	CPY	#0
	BEQ	PAST_RIGHT


CS50B:	TSX
	TXA
	SEC
	SBC	#17		;FIX THE STACK
	TAX
	TXS


CS53:  	JSR	FINDCOL		;FIND THIS COLUMN WITHIN THE SOLID DATA


	LDA	BACKWIDE
	SEC
	SBC	SUBSVAR6	;MAKE COLUMNS LEFT TO END OF BACKGROUND
	STA	SUBSVAR3
	LDA	SUBSVAR4	;GET COLUMNS TO CHECK
	SEC
	SBC	SUBSVAR3	;MAKE AMOUNT TOO MANY
	BCS	CS51
	LDA	#0		;IF WE HAVE MORE THAN ENOUGH, SET TO 0
CS51:	STA	SUBSVAR3	;SAVE AMOUNT TOO MANY HERE
	TAX			;BUT ALSO NEED A COPY

	LDA	SUBSVAR4
	SEC
	SBC	SUBSVAR3	;MAKE AMOUNT WE CAN CHECK THIS PASS
	STA	SUBSVAR3	;SET AMOUNT TO CHECK THIS PASS
	STX	SUBSVAR4	;AND PUT NEXT PASSES' AMOUNT HERE.

	CLC
	ADC	FETCHCOL
	STA	FETCHCOL
	BCC	CS52
	INC	FETCHCOL+1	;MAKE POINT TO CHECK NEXT LOOP


CS52: 

IFDEF( `BLOCKMODE', `		
	LDA	FETCHROW
	AND	#7		;GET ROW WITHIN BACKGROUND
	ASL	A
	ASL	A
	ASL	A		;MAKE *8
	TAX
	LDY	#0		;MAKE Y:X = POINTER WITHIN BACKGROUND
	', `
	LDX	FETCHROW
	LDY	BACKWIDE
	JSR	MUL		;MAKE Y:X = POINTER WITHIN BACKGROUND
	' )

	LDA	SUBSVAR6
	JSR	ADD_WORD		;MAKE POINTER TO DATA BLOCK
	TXA
	CLC
	ADC	BACKBASE
	STA	SUBSVAR1
	TYA
	ADC	BACKBASE+1
	STA	SUBSVAR2	;MAKE (SUBSVAR1) POINT TO DATA


	LDA	SUBSVAR3		;GET COUNT WE ARE GOING TO FETCH
	STA	SUBSVAR6		;SAVE IT HERE CAUSE FILLSTACK ZEROS IT
	JSR	FILLSTACK		;GET THE DATA WE WANTED

	LDY	SUBSVAR6		;GET BACK THE COUNT WE LOADED
	LDX	SUBSVAR5		;NEED TO RESTORE SLOT INDEX
	LDA	ANIM_RAM+SL,X		;GET USER'S SOLID CHARACTER VALUE
	STA	SUBSVAR6		;SAVE IT HERE FOR COMPARE
	TSX
	INX			;POINT TO DATA WE GOT IN THE STACK AREA

CS110:	LDA	H'100,X		;GET A CHAR
	INX
	CMP	SUBSVAR6		;SOLID?
	BCS	CS200			;SKIP IF SO.
	DEY
	BNE	CS110


CS115:	LDA	SUBSVAR4	;GET AMOUNT LEFT TO CHECK
	BNE	CS53
	

MS40: 	LDA	#0		;RETURN OK FLAG
	JMP	CS210


CS200: 	STA	SOLIDCHAR	;SAVE FOR CALLER
	LDA	#4
CS210:	STA	SUBSVAR3	;SAVE THE RETURN FLAG
	TSX
	TXA
	CLC
	ADC	#17		;FIX THE STACK
	TAX
	TXS
	LDA	SUBSVAR3
	RTS


GETCHAR:
	LDA	TESTX		;GET DESIRED X LOCATION
	CLC
	ADC	XBACK		;MAKE OFFSET IN BACKGROUND
	STA	FETCHCOL
	LDA	XBACK+1		
	ADC	#0
	LSR	A
	ROR	FETCHCOL
	LSR	A
	ROR	FETCHCOL
	LSR	A
	ROR	FETCHCOL	;MAKE FETCHCOL=TEXT COL,
	STA	FETCHCOL+1	

	LDA	TESTY
	CLC
	ADC	YBACK		;MAKE OFFSET IN BACKGROUND
	STA	FETCHROW
	LDA	#0
	ADC	YBACK+1

	LSR	A
	ROR	FETCHROW
	LSR	A
	ROR	FETCHROW
	LSR	A	
	ROR	FETCHROW	;MAKE TEXT ROW OF BOTTOM SPRITE

  	JSR	FINDCOL		;FIND THIS COLUMN WITHIN THE SOLID DATA


IFDEF( `BLOCKMODE', `		
	LDA	FETCHROW
	AND	#7		;GET ROW WITHIN BACKGROUND
	ASL	A
	ASL	A
	ASL	A		;MAKE *8
	TAX
	LDY	#0		;MAKE Y:X = POINTER WITHIN BACKGROUND
	', `
	LDX	FETCHROW
	LDY	BACKWIDE
	JSR	MUL		;MAKE Y:X = POINTER WITHIN BACKGROUND
	' )

	LDA	SUBSVAR6
	JSR	ADD_WORD		;MAKE POINTER TO DATA BLOCK
	TXA
	CLC
	ADC	BACKBASE
	STA	SUBSVAR1
	TYA
	ADC	BACKBASE+1
	STA	SUBSVAR2	;MAKE (SUBSVAR1) POINT TO DATA

	LDA	#1
	STA	SUBSVAR3	;SET COUNT WE ARE GOING TO FETCH
	PHA			;MAKE ROOM FOR 1 ON THE STACK
	JSR	FILLSTACK	;GET THE DATA WE WANTED
	PLA			;GET THE CHAR
	RTS


ZERO_ANIM:
 	LDA	#0
	TAX
ZA10:	STA	ANIM_RAM,X
	INX
	CPX	#SPMEM		;SEE IF DONE
	BNE	ZA10
	RTS


KILLSPRT:
	CMP	#-1		;FREE ALL?
	BNE	KS10


KILLALL:		;THIS IS AN ALLOWED USER ENTRY POINT.

	LDA	#0
KS5:	PHA
	JSR	KILLSPRT
	BNE	KS7
	PLA
	CLC
	ADC	#1		;JUST KEEP GOING USING THIS ROUTINE.
	JMP	KS5
KS7:	PLA
	LDA	#0
	RTS


KS10:	JSR	ANIMINDX
	BNE	KS50


MANUAL_KILL:
	LDA	ANIM_RAM+FB,X	;GET FLAG BYTE
	PHA
	LDA	#0
	STA	ANIM_RAM+FB,X	;FREE IT UP BEFORE RESETING HIDE BIT SO NMI
	PLA			;WON'T DO A FRAME UPDATE AND SET BIT AGAIN
	AND	#H'3
	BEQ	KS50		;IF DONE, END
	CMP	#3		;OBJECT?
	BEQ	KS50


	TXA
	PHA			;SAVE INDEX
	LDA	ANIM_RAM+BS,X	;GET BASE SPRITE INDEX
	TAY
	LDA	ANIM_RAM+PA,X		;SEE IF PREALLCOATION
	BNE	KS40
	LDA	ANIM_RAM+NS,X	;GET NUMBER TO HIDE
KS40:	TAX
	JSR	HIDE2		;USE THIS ROUTINE TO DO IT.
	PLA
	TAX

	LDA	#0
;DONE.  

KS50: 	RTS


INFRONT:
	STX	SUBSVAR1	;SAVE DESIRED CONDITION
	JSR	ANIMINDX
	BNE	IF4		;END IF BAD SLOT #

	LDA	ANIM_RAM+FB,X	;GET TYPE OF STRUCTURE
	AND	#H'3
	CMP	#1		;IF SIMPLE ANIMATION, WE ARE OK NOW
	BEQ	IF20
     	CMP	#2
	BEQ	IF20
	LDA	#1
IF4:	RTS


IF20:	LDY	ANIM_RAM+BS,X	;GET BASE SPRITE #
	LDA	ANIM_RAM+NS,X
	TAX			;AND COUNT

IF30:	LDA	SPRAM+2,Y	;GET THE BEHIND/IN USE BITS
	AND	#H'DF		;REMOVE THE BEHIND BIT
	EOR	SUBSVAR1	;PUT BACK IN IF DESIRED BY USER
	STA	SPRAM+2,Y	;SAVE BACK OUT
IF31:	INY
	INY
	INY
	INY			;SKIP TO NEXT SPRITE
	CPY	#252		;WRAP INDEX AT LAST SPRITE
	BEQ	IF31
	DEX
	BNE	IF30
	LDA	#0		;SUCCESS
	RTS

ALIGNANIM:
	STX	SUBSVAR3
	STY	SUBSVAR4	
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1
	AND	#H'CF		;REMOVE ANY OLD ALIGNMENT BITS
	ORA	SUBSVAR3	;SET IN THE NEW ONES
	STA	ANIM_RAM+FB,X
	LDA	SUBSVAR4	;GET ALIGNMENT VALUE
	AND	#H'7		;ONLY 3 BITS VALID
	STA	SUBSVAR4
	LDA	ANIM_RAM+AF,X	;GET THE AUXILIARY FLAGS
	AND	#H'F8		;REMOVE OLD BITS FOR ALIGNMENT
	ORA	SUBSVAR4
	STA	ANIM_RAM+AF,X	;SET BACK WITH NEW VALUE
	LDA	#0
	RTS


SOLID:
	STX	SUBSVAR3	;SAVE SOLID VALUE
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1.
	LDA	SUBSVAR3	;GET BACK SOLID VALUE
	STA	ANIM_RAM+SL,X	;SET NEW SOLID VALUE
	LDA	ANIM_RAM+FB,X
	ORA	#8
	LDY	SUBSVAR3	;SEE IF WE NEED TO TURN IT OFF (VALUE=0)
	BNE	SOLID10
	EOR	#8
SOLID10:
	STA	ANIM_RAM+FB,X	;SET THE FLAG 
	LDA	#0
	RTS


MIRROR:	STX	SUBSVAR3	;SAVE FLAG
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1
	LDA	ANIM_RAM+AF,X	;GET AUX FLAGS
	PHA			;SAVE A COPY
	AND	#B'10111111	;REMOVE THE MIRROR FLAG
	LDY	SUBSVAR3	;GET BACK MIRROR FLAG
	BEQ	MR10
	ORA	#H'40		;IF FLAG SET, SET MIRROR BIT
MR10:	STA	ANIM_RAM+AF,X	;PUT BACK NEW STATE
	STA	SUBSVAR3	;KEEP A COPY
	PLA			;GET ORIGINAL
	EOR	SUBSVAR3	;SEE IF BITS ARE SAME
	AND	#H'C0
	BEQ	MR20
	JSR	SPFRAME		;IF CHANGE, UPDATE ANIMATION
MR20:	LDA	#0
	RTS


INVERT:	STX	SUBSVAR3	;SAVE FLAG
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1
	LDA	ANIM_RAM+AF,X	;GET AUX FLAGS
	PHA			;SAVE A COPY
	AND	#H'7F		;REMOVE THE INVERT FLAG BIT
	LDY	SUBSVAR3	;GET BACK INVERT FLAG
	BEQ	IN10
	ORA	#H'80		;IF FLAG SET, SET INVERT BIT
IN10:	JMP	MR10


AUTOFREEZE:
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1
	LDA	ANIM_RAM+AF,X	;GET AUX FLAGS
	ORA	#H'10		;SET AUTOFREEZE FLAG
	STA	ANIM_RAM+AF,X	;PUT BACK NEW STATE
	LDA	#0
	RTS


SETALLOCATION:
	JSR	ANIMINDX
	BNE	SALCT
	LDA	ALLOCATION
	STA	ANIM_RAM+PA,X	;SET THE BYTE
	LDA	#0
SALCT:	RTS


GETFRAME:
	JSR	USEDINDX	;CHECK FOR ERRORS -1 AND 1
	LDA	ANIM_RAM+FR,X	;GET FRAME NUMBER	
	TAX
	LDA	#0		;RETURN NO ERROR
	RTS


USEDINDX:
	JSR	ANIMINDX
	BNE	UDX10
	LDA	ANIM_RAM+FB,X
	BEQ	UDX5
	RTS

UDX5:	LDA	#1	;IF UNUSED, RETURN 1 VALUE
UDX10:	TAX		;SAVE ERROR CODE
	PLA		;POP THE RETURN ADDRESS OF CALLER
	PLA		;POP THE RETURN ADDRESS OF CALLER
	TXA
	RTS		;AND RETURN TO HIS CALLER WITH CORRECT ERROR


ANIMINDX:
	CMP	#SPSLOTS	;VALID VALUE TO FREE UP?
	BCS	AX40		;SKIP IF NOT

	TAX
	LDY	#ANIM_WIDE
	JSR	MUL
	LDA	#0
	RTS

AX40:	LDA	#-1
	RTS


SPFRAME:
	TXA
	PHA

  	LDA	ANIM_RAM+FB,X
	AND	#H'3
	CMP	#1
	BNE	SPF5

	LDA	ANIM_RAM+PTRL,X	;IF JUST SPRITE AND NOT ANIMATION, USE PTR
	STA	SUBSVAR1
	LDA	ANIM_RAM+PTRH,X
	STA	SUBSVAR2
	JMP	SPF25

SPF5:	LDA	ANIM_RAM+FR,X	;GET CURRENT FRAME
	LDY	#0
	ASL	A
	BCC	SPF10
	LDY	#1		;MAKE Y:A=OFFSET IN ANIMATION LIST
SPF10:	CLC
	ADC	#3		;AND NEED TO SKIP FLAG BYTES
	BCC	SPF20
	INY			;MOVE UP ANY CARRY
SPF20:	CLC
	ADC	ANIM_RAM+PTRL,X	;ADD IN THE LOW POINTER
	STA	SUBSVAR1
	TYA
	ADC	ANIM_RAM+PTRH,X	;ADD IN HIGH
	STA	SUBSVAR2	;NOW HAVE POINTER TO THE NEXT FRAME'S OFFSET
	LDY	#0
	LDA	(SUBSVAR1),Y	;GET LOW
	PHA
	INY
	LDA	(SUBSVAR1),Y	;GET HIGH
	STA	SUBSVAR2
	PLA
	STA	SUBSVAR1	;NOW HAVE POINTER TO THE DATA


SPF25: 	LDY	#1		;POINT TO WIDTH OF SPRITE
	LDA	(SUBSVAR1),Y

IFDEF( `COMPRESS_SPRITES', `
	LSR	A
	LSR	A
	LSR	A
	LSR	A		;Get width from high nybble
	', `
	INY			;POINT TO HEIGHT
	')

	STA	MATH1		;SAVE HERE
	LDA	(SUBSVAR1),Y

IFDEF( `COMPRESS_SPRITES', `
	AND	#15		;Width is in low nybble.
	', )

	STA	MATH2		;SAVE HERE AS LOOP COUNTER
	INY			;POINT TO DATA

	LDA	ANIM_RAM+AF,X	;GET INVERT/MIRROR STATE
	AND	#H'C0		;KEEP THESE BITS
	STA	MATH3		;SAVE HERE
	BMI	SPF30		;SKIP


	AND	#H'40		;SEE IF MIRRORED
	BNE	SPF28
	LDA	#4
	STA	SUBSVAR3	;4 BEFORE EACH SPRITE
	LDA	#0
	STA	SUBSVAR4	;0 AT EACH ROW'S END
	STA	SUBSVAR5	;AND SET TO ADD IT
	LDA	ANIM_RAM+BS,X	
SPF26:	SEC
	SBC	#4		;START 4 DOWN
	BCC	SPF26		;BUT NEED TO SKIP FC IF WE END UP ON IT.
	TAX
	JMP	SPF50		;GO DO IT


SPF28:	LDA	#-4
	STA	SUBSVAR3	;-4 BEFORE EACH SPRITE
	LDA	MATH1
	ASL	A
	ASL	A		;MAKE WIDTH*4
	STA	MATH4
	ASL	A
	STA	SUBSVAR4	;2*WIDTH*4 PER SPRITE AT EACH ROW'S END
	LDA	#0
	STA	SUBSVAR5	;SET TO ADD IT
	LDA	MATH4		;GET WIDTH*4
	CLC
	ADC	ANIM_RAM+BS,X	;START 1 ROW UP
	BCS	SPF29
	CMP	#252		;BUT WE MUST SKIP THIS ONE
	BNE	SPF29A	
SPF29:	CLC
	ADC	#4		;IF PASS 0, SKIP FC
SPF29A:	TAX
	JMP	SPF50		;GO DO IT


SPF30:	AND	#H'40		;SEE IF MIRRORED
	BNE	SPF35	

	LDA	#4
	STA	SUBSVAR3	;4 BEFORE EACH SPRITE
	LDA	MATH1
	ASL	A
	ASL	A
	STA	MATH4
	ASL	A
	STA	SUBSVAR4	;-2*WIDTH AT EACH ROW'S END

	LDA	ANIM_RAM+NS,X
	ASL	A
	ASL	A
	SEC
	SBC	MATH4
	SEC
	SBC	#4		;MAKE END-WIDTH*4-4
	STA	SUBSVAR5	;SAVE FOR SUBTRACTING

	LDA	ANIM_RAM+BS,X	;POINT TO END
	CLC
	ADC	SUBSVAR5
	BCS	SPF31
	CMP	#252		;BUT WE MUST SKIP THIS ONE
	BNE	SPF31A	
SPF31:	CLC
	ADC	#4		;IF PASS 0, SKIP FC
SPF31A:	TAX	     		;START AT END-WIDTH*4-4

	LDA	#-1
	STA	SUBSVAR5	;SET FLAG TO SUBTRACT THE SUBSVAR4 VALUE
	JMP	SPF50		;GO DO IT


SPF35:	LDA	#-4
	STA	SUBSVAR3	;-4 BEFORE EACH SPRITE
	LDA	#0
	STA	SUBSVAR4	;0 AT EACH ROW'S END
	STA	SUBSVAR5	;SET TO ADD IT.
	LDA	ANIM_RAM+NS,X
	ASL	A
	ASL	A
	CLC
	ADC	ANIM_RAM+BS,X	;POINT TO END
	BCS	SPF36
	CMP	#252		;BUT WE MUST SKIP THIS ONE
	BNE	SPF36A	
SPF36:	CLC
	ADC	#4		;IF PASS 0, SKIP FC
SPF36A:	TAX	     		;START AT END


SPF50: 	LDA	MATH1
	STA	MATH4		;SET A LOOP COUNT FOR THE ROW

SPF60:	TXA
	CLC
	ADC	SUBSVAR3	;CORRECT TO NEXT SPRITE
	CMP	#252		;WE ONLY HAVE 63 SPRITES CAUSE OF TOPSPRITE
	BNE	SPF61
	CLC
	ADC	SUBSVAR3	;CORRECT TO NEXT SPRITE
SPF61:	TAX
	LDA	(SUBSVAR1),Y	;GET CHAR TO USE
	STA	SPRAM+1,X	;SET CHAR INTO SPRITE
	INY			;POINT TO PAL/FLIP INFO
	LDA	SPRAM+2,X	;GET THE BEHIND BIT
	AND	#H'20		;KEEP IT
	ORA	#8		;ALWAYS SET IN USE FOR INITSPRT
	ORA	(SUBSVAR1),Y	;MOVE INTO PAL INFO
	EOR	MATH3		;TOGGLE MIRROR/INVERT BITS CONDITION
	STA	SPRAM+2,X	;SAVE BACK OUT
	INY			;SKIP TO NEXT SPRITE
	DEC	MATH4		;COUNT 1 MORE ON THIS ROW
	BNE	SPF60

	TXA			;TIME TO CORRECT FOR ROW
	LDX	SUBSVAR5	;SEE IF ADD OR SUBTRACT THIS VALUE
	BPL	SPF61A
	SEC
	SBC	SUBSVAR4	;WE NEED TO SUBTRACT IT
	BCS	SPF62		;A CARRY MEANS IT WAS OK
	SEC
	SBC	#4		;OTHERWISE WE NEED ADJUSTMENT
	JMP	SPF62

SPF61A:	CLC
	ADC	SUBSVAR4
	BCS	SPF61B		;IF CARRY, GO ADD 4.
	CMP	#252		;IF NO CARRY, IS IT EXACTLY THE ILLEGAL VALUE?
	BNE	SPF62
SPF61B:	CLC
	ADC	#4

SPF62:	TAX
	DEC	MATH2		;WHEN ROW IS DONE, COUNT 1 MORE ROW
	BNE	SPF50

	PLA
	TAX
	RTS


CHECK_ANIM:

	LDX	#0		;POINT TO THE SLOTS
	LDY	#SPSLOTS	;GET COUNT TO CHECK


CA10: 	TYA
	PHA			;SAVE LOOP COUNT
	LDA	ANIM_RAM+FB,X	;GET THE FLAG BYTE
	AND	#H'3		;KEEP ONLY ID BITS
	TAY			;KEEP COPY HERE
	BNE	CA20		;SKIP IF TRUE.  MEANS SLOT IN USE.

CA15: 	PLA
	TAY			;GET BACK LOOP COUNT
	TXA
	CLC
	ADC	#ANIM_WIDE	;SKIP TO NEXT
	TAX
	DEY
	BNE	CA10
	RTS


CA20:	TYA
 	CMP	#1
	BEQ	CA15


	LDA	ANIM_RAM+FB,X
	AND	#H'70
	BEQ	CA25
	TYA				;GET BACK TYPE
	JMP	CA37			;IF NOT COUNTING, NEED UPDATE ANYWAY?	

CA25:	DEC	ANIM_RAM+CN,X
	BNE	CA37


	TYA
	CMP	#3
	BNE	CA30
	LDA	ANIM_RAM+NS,X
	ORA	#H'80
	STA	ANIM_RAM+NS,X


CA30: 	LDA	ANIM_RAM+RL,X
	STA	ANIM_RAM+CN,X
	LDA	ANIM_RAM+PTRL,X
	STA	NMI_PTR
	LDA	ANIM_RAM+PTRH,X
	STA	NMI_PTR+1

	INC	ANIM_RAM+FR,X	;INC FRAME
	LDA	ANIM_RAM+FR,X	;GET IT
	LDY	#1		;POINT TO THE FRAMES IN DEFFINITION
	CMP	(NMI_PTR),Y	;HIT END OF LIST?
	BNE	CA35
	LDA	ANIM_RAM+AF,X	;SEE IF AUTOFREEZE
	AND	#H'10
	BEQ	CA32
	LDA	ANIM_RAM+FB,X
	ORA	#H'40
	STA	ANIM_RAM+FB,X	;FREEZE IT IF SO
	DEC	ANIM_RAM+FR,X	;AND FIX IT, WE CHANGED IT LAST TIME.
	JMP	CA15	     	

CA32:	LDA	#0
	STA	ANIM_RAM+FR,X	;RESET IF TOO BIG

CA35:	LDA	ANIM_RAM+FB,X
	AND	#3
	CMP	#2
	BNE	CA37
	JSR	SPFRAME		;THIS ROUTINE WILL DO IT
CA37:	JMP	CA15		;AND NOT A BACKGROUND FOR SURE.


INSTRUMENTS:	

.DB	H'C0,H'00          		;BASE_HARPSI
.DB	H'C0,H'00          		;HARPSI
.DB	H'C0,H'00          		;HIGH_HARPSI    
.DB	H'80,H'00          		;BASE_STRING
.DB	H'80,H'00          		;STRING
.DB	H'80,H'00          		;HIGH_STRING    
.DB	H'00,H'00          		;BASE_ELECPIANO
.DB	H'00,H'00          		;ELECPIANO
.DB	H'00,H'00          		;HIGH_ELECPIANO
.DB	H'80,H'FF          		;BASE_SLIDER
.DB	H'80,H'FF          		;SLIDER
.DB	H'80,H'FF          		;HIGH_SLIDER   
.DB	H'00,H'D6          		;BASE_BEE
.DB	H'00,H'D6          		;BEE
.DB	H'00,H'D6          		;HIGH_BEE
.DB	H'40,H'00          		;BASE_PIANO
.DB	H'40,H'00          		;PIANO
.DB	H'40,H'00          		;HIGH_PIANO
.DB 	H'80,H'C9			;BASE_ARCADE
.DB 	H'80,H'C9			;ARCADE
.DB 	H'80,H'C9			;HIGH ARCADE


FEED_SOUND:

	TSX
	TXA
	SEC
	SBC	#6		;MAKE ROOM TO HOLD DATA FOR SOUND COMMANDS
	TAX
	TXS
	INX			;POINT TO WHERE IT WILL GO
	STX	TMP_NMIE	;MAKE THIS A POINTER TO THE DATA WE GOT

	LDX	#0		;START WITH THE LOWEST SOUND SLOT.
	STX	FOUNDSOME	;SET FLAG OF DIDN'T FIND AN ACTIVE ONE	
FS20:	LDA	SND_RAM+SF,X	;GET THE SOUND FLAG
	BPL	FS30		;IF NOT IN USE, SKIP IT


	STA	FOUNDSOME	;SET FLAG OF FOUND ONE

	DEC	SND_RAM+ST,X	;COUNT IT DOWN
	BEQ	FS50		;IF REACHES ZERO, TIME FOR MORE PROCESSING	


FS30:	TXA
	CLC
	ADC	#SND_WIDE
	TAX
	CMP	#SND_WIDE*SNDSLOTS	;END OF LIST?
	BCC	FS20			;IF NOT, CONTINUE


	LDA	FOUNDSOME
	BNE	FS31
	LDA	#0
	STA	DRUMLOCK	;UNLOCK DRUMS IN CASE USER FORGETS ALLOWDRUMS
	STA	REG4015
	STA	H'4015		;DISABLE ALL WHEN NO SLOTS ACTIVE.
FS31: 	TSX
	TXA
	CLC
	ADC	#6		;REMOVE EXTRA ROOM WE MADE IN STACK
	TAX
	TXS			;FIX STACK
	RTS


FS50:	LDA	SND_RAM+SOL,X		;GET LOW OFFSET OF NEXT BYTE TO USE
	STA	SUBSVAR1
	LDA	SND_RAM+SOH,X		;GET HIGH
	STA	SUBSVAR2		;MAKE POINTER TO THE NEXT BYTE
	STX	TMP_NMID		;SAVE OUR INDEX
	LDA	#5
	STA	SUBSVAR3
	JSR	FILLSTACK		;GET THE LARGEST POSSIBLE COMMAND
	LDX	TMP_NMID		;GET BACK OUR INDEX


	LDY	TMP_NMIE		;POINT TO THE DATA
FS60:	LDA	H'100,Y
	AND	#B'11100000		;SEE IF JUST A NOTE
	CMP	#B'10100000		;NOTES END BELOW THIS
	BCS	FS200


	LDA	H'100,Y			;GET BACK DURATION
	JSR	SET_DURATION		;SET DURATION, RESTORE INSTRUMENT
	BNE	FS70			;IF SUSPENDED, DON'T WASTE TIME
	
	LDA	NMI_PTR			;SEE IF PERCUSSION INSTRUMENT FLAG
	CMP	#H'1F
	BEQ	FS100			;SKIP IF IT IS (PERCUSSION)

	LDA	SND_RAM+SI,X		;GET INSTRUMENT TYPE
	ASL	A			;MAKE *2 POINTER
	TAY
	LDA	FREQBASES,Y		;GET LOW BASE OF FREQUENCY TABLE
	STA	NMI_PTR
	LDA	FREQBASES+1,Y
	STA	NMI_PTR+1		;MAKE POINTER TO FREQUENCY TABLE
	LDY	TMP_NMIE
	LDA	H'100,Y			;GET NOTE TO USE
	AND	#H'1F
	CMP	#PAUSE			;SILENCE?
	BEQ	FS70
	ASL	A			;MAKE INDEX FROM IT
	TAY
	LDA	(NMI_PTR),Y
	STA	SUBSVAR3
	INY
	LDA	(NMI_PTR),Y
	STA	SUBSVAR4		;SET FREQUENCY TO USE
	JSR	SET_FREQUENCY
FS70:  	JSR	INC_INDX
	JMP	FS30
     
	
FS100:	TXA
	PHA			;SAVE OUR INDEX
	LDA	H'100,Y		;GET LOW 5 BITS TO FIND BASE OF PERCUSSION
	AND	#H'1F		;IN THE PERCUSSION TABLE.
	AND	#H'1F
	CMP	#PAUSE			;SILENCE?
	BEQ	FS115
	STA	SUBSVAR4	;SAVE A COPY
	ASL	A
	ASL	A		;MAKE *4 POINTER
	CLC
	ADC	SUBSVAR4	;MAKE *5 POINTER
	TAX
FS110:	LDA	PERCTABLE,X
	STA	NMI_PTR		;SET CORRECT BASE FROM FIRST BYTE
	INX
	JSR	FINISH_BIT	;MAKE TEST BIT FOR DRUMLOCK
	AND	DRUMLOCK
	BNE	FS115

	LDY	#0
FS111:	LDA	PERCTABLE,X
	STA	(NMI_PTR),Y	;SET THE INSTRUMENT
	INX
	INY
	CPY	#4
	BNE	FS111
FS115:	PLA
	TAX
	JMP	FS70


FS200:	CMP	#B'10100000	;SELECT INSTRUMENT?
	BNE	FS220
	LDA	H'100,Y		;GET BACK INSTRUMENT
	AND	#H'1F
	STA	SND_RAM+SI,X	;PUT INTO SLOT
	LDA	SND_RAM+SF,X	;SEE IF SUSPENDED OR NO BASE
	AND	#H'60
	BNE	FS210
	JSR	INITSND		;INITIALIZE FOR THIS INSTRUMENT


FS210:	JSR	INC_INDX
	LDA	#1
	STA	SND_RAM+ST,X	;SET TIMER FOR NEXT NMI
	JMP	FS30
	

FS220:	LDA	H'100,Y
 	CMP	#SOUNDLOOP	;SOUND LOOP?
	BNE	FS230

	LDA	SND_RAM+LOP,X	;SEE IF WE ARE ALREADY LOOPING
	BNE	FS221
	LDA	H'101,Y
	STA	SND_RAM+LOP,X	;SET LOOP COUNT FOR A NEW TIME
FS221:	DEC	SND_RAM+LOP,X	;LOWER COUNT OF TIMES LEFT TO LOOP
	BEQ	FS222
	LDA	H'102,Y		;GET LOW ADDRESS TO LOOP TO
	STA	SND_RAM+SOL,X
	LDA	H'103,Y
	STA	SND_RAM+SOH,X	;SET US BACK TO THAT ADDRESS
	JMP	FS50		;AND RUN NEW LOCATION SO THIS TAKES NO TIME

FS222:	JSR	INC_INDX	;WE ARE DONE LOOPING
	JSR	INC_INDX
	JSR	INC_INDX
	JSR	INC_INDX
	JMP	FS50


FS230:	CMP	#NODRUMS
	BNE	FS235
	JSR	ENABLE_BIT
	ORA	DRUMLOCK
	STA	DRUMLOCK	;SET BIT TO LOCK OUT THE DRUM
	JMP	FS210

FS235:	CMP	#ALLOWDRUMS
	BNE	FS240
	JSR	ENABLE_BIT
	PHA
	ORA	DRUMLOCK
	STA	DRUMLOCK
	PLA
	EOR	DRUMLOCK
	STA	DRUMLOCK
	JMP	FS210


FS240:	LDA	H'100,Y		;GET THE EXTENDED BITS
	AND	#B'00011111	;KEEP THEM AND THE DATA BITS TOO.
	CMP	#B'00000011+1	;SEE IF SPECIFY VOICE COMMAND
	BCS	FS260

	AND	#3		;GET THE VOICE TO USE
	ASL	A
	ASL	A		;MAKE *4 BASE POINTER

FS245: 	PHA			;SAVE VOICE BASE BITS
	LDA	SND_RAM+SF,X	;GET CURRENT VALUE
	AND	#H'E0		;REMOVE THE BITS THAT SELECT THE BASE REG
	STA	SND_RAM+SF,X
	PLA
	ORA	SND_RAM+SF,X	;PUT NEW REGISTER BASE INTO THE FLAG BYTE
	AND	#H'9F		;REMOVE REGISTER NOT SELECTED BIT AND SUSPEND
	STA	TMP_NMI1	;SAVE HERE FOR CHECK FOR OTHER'S USING IT
	STA	SND_RAM+SF,X
	STX	TMP_NMI2	;SAVE OUR INDEX

	LDX	#0
FS250:	LDA	SND_RAM+SF,X	;GET A FLAG BYTE
	EOR	TMP_NMI1	;SEE IF THAT SOUND SLOT IS USING THIS VOICE
	BNE	FS255
      	LDA	SND_RAM+SF,X
	ORA	#H'20		;IF SO, SUSPEND HIM
	STA	SND_RAM+SF,X
FS255:	TXA
	CLC
	ADC	#SND_WIDE
	TAX
	CMP	#SND_WIDE*SNDSLOTS	;DONE?
	BCC	FS250

	LDX	TMP_NMI2	;GET BACK OUR INDEX
	LDA	TMP_NMI1	;AND OUR FLAG BYTE
	STA	SND_RAM+SF,X	;PUT BACK OUR FLAG CAUSE OUR LOOP SUSPENDED US
	JSR	ENABLE_VOICE	;AND ENABLE OUR VOICE
	JMP	FS210

FS260:	CMP	#B'00000111+1	;REPEAT LIST?
	BCS	FS280
	LDA	SND_RAM+SBL,X
	STA	SND_RAM+SOL,X
	LDA	SND_RAM+SBH,X
	STA	SND_RAM+SOH,X	;IF SO, JUST RESET POINTER
	JMP	FS210		;AND SKIP THIS COMMAND.


FS280:	CMP	#B'00001011+1	;END LIST?
	BCS	FS300
	TXA
	PHA
	JSR	S20		;USE THE SILENCE ROUTINE'S SPECIAL ENTRY PNT.
	PLA
	TAX
	JMP	FS210

FS300:	CMP	#B'00001111+1	;ABSOLUTE REG LOAD?
	BCS	FS320

	LDA	SND_RAM+SF,X
	AND	#H'60
	BNE	FS311		;SKIP IT IF NOT SELECTED OR SUSPENDED

FS310:	LDA	SND_RAM+SF,X	;GET REG BASE FOR THIS VOICE
	AND	#H'1F		;KEEP THE REG OFFSET
	STA	SUBSVAR3
	LDY	TMP_NMIE
	LDA	H'100,Y		;GET LOW 2 BITS OF REG TO USE
	AND	#3
	CLC
	ADC	SUBSVAR3	;MAKE IT INTO A POINTER
	STA	NMI_PTR
	LDA	#H'40
	STA	NMI_PTR+1	;AND POINT TO THE REG AT 40XX
	LDY	TMP_NMIE
	LDA	H'101,Y		;GET VALUE TO USE
	LDY	#0
	STA	(NMI_PTR),Y	;PUT IT OUT THERE
FS311:	JSR	INC_INDX		;SKIP THE EXTRA BYTE WE USED
	JMP	FS210	

FS320:	CMP	#B'00010011+1	;DISABLE SOUND?
	BCS	FS340
	JSR	DISABLE_VOICE
	JMP	FS210

FS340:	CMP	#B'00010111+1	;ENABLE SOUND?
	BCS	FS360
	JSR	ENABLE_VOICE
	JMP	FS210

FS360:	CMP	#PERCUSSION & B'00011111 	;USE PERCUSSION INSTRUMENTS?
	BNE	FS365
	LDA	SND_RAM+SF,X	;GET CURRENT VALUE
	AND	#H'E0		;REMOVE THE BITS THAT SELECT THE BASE REG
	ORA	#H'1F		;SET ALL BITS TO FLAG PERCUSSION
	AND	#H'9F		;REMOVE REGISTER NOT SELECTED BIT AND SUSPEND
	STA	SND_RAM+SF,X	;PUT IT BACK FOR THE NOTE COMMANDS TO DETECT
	JSR	ENABLE_VOICE	;ENABLE OUR VOICES
	JMP	FS210

FS365:	CMP	#LOADALL & B'00011111	;LOAD ALL REGS?
	BNE	FS380

	LDA	SND_RAM+SF,X
	AND	#H'60
	BNE	FS367		;SKIP IT IF NOT SELECTED OR SUSPENDED

	LDA	SND_RAM+SF,X	;GET REG BASE FOR THIS VOICE
	AND	#H'1F		;KEEP THE REG OFFSET
	STA	NMI_PTR
	LDA	#H'40
	STA	NMI_PTR+1	;AND POINT TO THE REG AT 40XX

	LDA	TMP_NMIE
	STA	TMP_NMIC
	LDY	#0
FS366: 	STY	TMP_NMID
	INC	TMP_NMIC
	LDY	TMP_NMIC
	LDA	H'100,Y		;GET VALUE TO USE
	LDY	TMP_NMID
	STA	(NMI_PTR),Y	;PUT IT INTO THE CORRECT REGISTER
	INY
	CPY	#5
	BNE	FS366

FS367:	JSR	INC_INDX		;SKIP THE EXTRA BYTES WE USED
	JSR	INC_INDX		
	JSR	INC_INDX		
	JSR	INC_INDX		
	JMP	FS210	

FS380:	CMP	#WAIT & B'00011111	;FIXED DELAY?
	BNE	FS390
	LDY	TMP_NMIE
	LDA	H'101,Y		;GET VALUE TO USE FOR THE DELAY
	STA	SND_RAM+ST,X	;RELOAD THE TIMER
	JSR	INC_INDX
	JSR	INC_INDX
	JMP	FS30


FS390:	JMP	FS210


ENABLE_VOICE:

	JSR	ENABLE_BIT
	ORA	REG4015
	STA	REG4015
	STA	H'4015		;ENABLE IT AND SAVE VALUE FOR OTHERS TO REF.
	RTS


DISABLE_VOICE:
	JSR	ENABLE_BIT
	CMP	#PERCENABLE	;PERCUSSION INSTRUMENT?
	BEQ	DVC10		;IF SO, DON'T DO IT.
	EOR	#H'FF
	AND	REG4015
	STA	H'4015
	LDA	REG4015
	STA	H'4015		;DISABLE IT AND SAVE STATE	
DVC10:	RTS


ENABLE_BIT:
	LDA	SND_RAM+SF,X	;GET THE REGISTERS TO USE
	AND	#H'1F
	CMP	#H'1F		;PERCUSSION?
	BEQ	EB30

FINISH_BIT:			;CALL HERE WITH YOUR OWN BASE REG TO MAKE
				;BIT IN A.J  ONLY A AND Y ARE CHANGED.
	LSR	A
	LSR	A		;MAKE INTO UNIQUE NUMBER 0-4
	TAY
	LDA	ENABIT,Y	;GET THE BIT POSITION
	RTS

ENABIT:	.DB	1,2,4,8,H'10

EB30:	LDA	#PERCENABLE	;IF PERCUSSION, ENABLE THOSE USED.
	RTS


TIME_BASE:
.DB	8,1			;1/16 NOTE
.DB	16,5			;1/8 NOTE
.DB	32,8			;1/4 NOTE
.DB	64,15			;1/2 NOTE
.DB	128,31			;WHOLE NOTE


.EQU	BSD0,0		;BASE DRUM FOR VOICE 0
.EQU	BSD1,1		;BASE DRUM FOR VOICE 1
.EQU	TOM0,2		;TOM DRUM FOR VOICE 0
.EQU	TOM1,3		;TOM DRUM FOR VOICE 1
.EQU	SN0,4		;SNARE FOR VOICE 0
.EQU	SN1,5		;SNARE FOR VOICE 1
.EQU	RIM,6		;RIM SHOT
.EQU	BRS,7		;BRUSH
.EQU	HIBELL,8	;HIGH BELL
.EQU	TRI,9		;HIGH TRIANGLE
.EQU	HH,10		;HIGH HAT
.EQU	TOM2,11		;TOM DRUM FOR VOICE 2
.EQU	HITOM0,12	;HIGH TOM FOR VOICE 0
.EQU	HITOM1,13	;HIGH TOM FOR VOICE 1
.EQU	LOWTOM0,14	;HIGH TOM FOR VOICE 0
.EQU	LOWTOM1,15	;HIGH TOM FOR VOICE 1


.EQU	PERCENABLE,B'00001111	;VOICES TO ENABLE FOR PERCUSSION

PERCTABLE:
.DB	H'00,H'80,H'86,H'FF,H'0C	;BASE DRUM
.DB	H'04,H'80,H'86,H'FF,H'0C
.DB	H'00,H'80,H'84,H'00,H'8B	;TOM
.DB	H'04,H'80,H'84,H'00,H'8B
.DB	H'00,H'80,H'84,H'FF,H'0B
.DB	H'04,H'80,H'84,H'FF,H'0B
.DB	H'0C,H'00,H'00,H'08,H'02
.DB	H'0C,H'01,H'01,H'03,H'09	;BRUSH
.DB	H'0C,H'0F,H'00,H'92,H'C7
.DB	H'0C,H'05,H'00,H'81,H'08
.DB	H'0C,H'03,H'00,H'04,H'50	;HI HAT
.DB	H'08,H'04,H'00,H'F5,H'30	;TOM2
.DB	H'00,H'80,H'84,H'00,H'89	;HIGH TOM
.DB	H'04,H'80,H'84,H'00,H'89
.DB	H'00,H'80,H'84,H'00,H'8E	;LOW TOM
.DB	H'04,H'80,H'84,H'00,H'8E

SET_DURATION:

	LSR	A
	LSR	A
	LSR	A
	LSR	A		;MOVE BITS DOWN TO MAKE *2 INDEX
	AND	#H'FE		;MAKE SURE INDEX IS EVEN
	TAY			;USE INDEX HERE
	LDA	TIME_BASE,Y	;GET THE TIME BASE FOR OUR SOUND STRUCTURE
	STA	SND_RAM+ST,X	;RELOAD THE TIMER

	JSR	SELECTED	;SEE IF SUSPENDED OR NO REGS SELECTED
	BNE	SD60

	INY
	LDA	TIME_BASE,Y	;GET THE RELOAD BITS FOR THE LOW REGISTER
	STA	TMP_NMI1	;SAVE IT HERE

	JSR	MAKEBASE	;MAKE (NMI_PTR) TO THE SOUND REGS

	LDA	SND_RAM+SI,X	;GET INSTRUMENT
	ASL	A		;MAKE *2 POINTER FROM IT
	TAY
	LDA	INSTRUMENTS+1,Y	;GET SECOND REGISTER THAT SPECIFIES INSTRUMENT
	PHA			;SAVE IT
	LDA	INSTRUMENTS,Y	;GET REGISTER VALUE TO LOAD
	ORA	TMP_NMI1	;OR IN THE TIME BASE
	LDY	#0
	STA	(NMI_PTR),Y	;PUT INTO THE SOUND CHIP
	INY
	PLA
	STA	(NMI_PTR),Y	;PUT SECOND REG THERE TOO
	LDY	#0
SD60:	RTS


MAKEBASE:
	LDA	SND_RAM+SF,X	;GET REGISTER BASE
	AND	#H'1F		;MAKE BASE REG
	STA	NMI_PTR
	LDA	#H'40
	STA	NMI_PTR+1	;INTO A POINTER WE CAN USE
	RTS


FREQBASES:

.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ,HIGH_FREQ
.DRW	LOW_FREQ,MID_FREQ


LOW_FREQ:
.DRW	H'352		;C	
.DRW	H'325		;C#	
.DRW	H'2FD		;D	
.DRW	H'2CC		;Eb	
.DRW	H'2A7		;E	
.DRW	H'27C		;F	
.DRW	H'25A		;F#	
.DRW	H'23B		;G	
.DRW	H'213		;Ab	
.DRW	H'1FD		;A	
.DRW	H'1DE		;Bb	
.DRW	H'1C6		;B	

MID_FREQ:
.DRW	H'1AB		;C	
.DRW	H'191		;C#	
.DRW	H'17A		;D	
.DRW	H'167		;Eb	
.DRW	H'151		;E	
.DRW	H'13F		;F	
.DRW	H'12C		;F#	
.DRW	H'11C		;G	
.DRW	H'10D		;Ab	
.DRW	H'FE 		;A	
.DRW	H'EF 		;Bb	
.DRW	H'E2 		;B	

HIGH_FREQ:
.DRW	H'D5  		;MIDDLE C	
.DRW	H'C8		;C#	
.DRW	H'BE		;D	
.DRW	H'B3		;Eb	
.DRW	H'A9		;E	
.DRW	H'9F		;F	
.DRW	H'96		;F#	
.DRW	H'8E		;G	
.DRW	H'86		;Ab	
.DRW	H'7E		;A	
.DRW	H'77		;Bb	
.DRW	H'70		;B	
.DRW	H'6A		;C	
.DRW	H'64		;C#	
.DRW	H'5E		;D	
.DRW	H'59		;Eb	
.DRW	H'54		;E	
.DRW	H'4F		;F	
.DRW	H'4B		;F#	
.DRW	H'46		;G	
.DRW	H'42		;Ab	
.DRW	H'3F		;A	
.DRW	H'3B		;Bb	
.DRW	H'38		;B	
.DRW	H'34		;C	
.DRW	H'32		;C#	
.DRW	H'2F		;D	
.DRW	H'2C		;Eb	
.DRW	H'29		;E	
.DRW	H'27		;F	
.DRW	H'24		;F#	
.DRW	H'23		;G	


SET_FREQUENCY:

	JSR	SELECTED	;SEE IF SUSPENDED OR NO REGS SELECTED
	BNE	SQ60

	JSR	MAKEBASE

	LDY	#2		;START WITH LOW REG LOAD
	LDA	SUBSVAR3
	STA	(NMI_PTR),Y
	INY
	LDA	SUBSVAR4	;THEN GET HIGH
	ORA	#8		;OR IN THE BIT TO USE DURATION REG
	STA	(NMI_PTR),Y
SQ60:	RTS


INC_INDX:
	INC	SND_RAM+SOL,X	;DONE, MOVE INDEX ALONG
	BNE	IX5
	INC	SND_RAM+SOH,X
IX5:	RTS


SELECTED:
	LDA	SND_RAM+SF,X	;GET BACK THE FLAG
	AND	#H'60		;SEE IF SUSPENDED OR NO REGS SELECTED
	RTS



INITSND:
	LDA	SND_RAM+SI,X	;GET INSTRUMENT
	ASL	A		;MAKE *2 POINTER FROM IT
	STA	SUBSVAR4	;SAVE IT HERE
	LDA	SND_RAM+SF,X	;GET BASE
	AND	#H'1F
	STA	SUBSVAR1
	LDA	#H'40
	STA	SUBSVAR2	;MAKE FULL POINTER TO IT IN MEMORY

 	LDY	SUBSVAR4
	LDA	INSTRUMENTS,Y	;GET REGISTER VALUE TO LOAD
	LDY	#0
	STA	(SUBSVAR1),Y	;PUT INTO CORRECT REGISTER
	LDY	SUBSVAR4
	INY			;GET NEXT REGISTER VALUE
	LDA	INSTRUMENTS,Y
	LDY	#1
	STA	(SUBSVAR1),Y	;PUT INTO NEXT REG
	RTS


SNDINDX:
	CMP	#SNDSLOTS	;VALID VALUE?
	BCS	SX40		;SKIP IF NOT

	TAX
	LDY	#SND_WIDE
	JSR	MUL
	LDA	#0
	RTS

SX40:	LDA	#-1
	RTS


DOPAL:	LDA	NEW_PAL		;SEE IF NEED INIT OF NEW PAL
	AND	#1
	BEQ	DP100


	EOR	NEW_PAL
	STA	NEW_PAL		;RESET BIT OF NEED INIT OF BACKGROUND
	LDY	#0
	LDA	(BPAL_BASE),Y
	STA	BPAL_BLINK	;SET BLINK FOR BACKGROUND
	INY
	LDA	(BPAL_BASE),Y
	STA	BPAL_DEPTH	;SET DEPTH OF BLINK
	INY
	LDA	#1
	STA	BPAL_INDX	;SET BLINK INDEX TO NEXT FRAME CAUSE 0 BOOTS.
	LDA	(BPAL_BASE),Y
	STA	BPAL_FREQ	;SET FREQUENCY
	STA	BPAL_CNT	;AND SET TIMER COUNT
	
	CLC
	LDA	BPAL_BASE
	ADC	#3
	STA	BPAL_BASE
	LDA	BPAL_BASE+1
	ADC	#0
	STA	BPAL_BASE+1	;POINT BASE DIRECTLY TO DATA

	LDX	SCCNT		;GET SCREEN BUFFER COUNT
	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	#H'3F
	STA	SCNBUF,X
	INX
	LDA	#H'00
	STA	SCNBUF,X
	INX
	LDA	#16
	STA	SCNBUF,X		;QUE UP WRITE LOCATION AND COUNT
	INX
	STA	TMP_NMI1	;AND MAKE A LOOP COUNT
	LDY	#0
DP10:	LDA	(BPAL_BASE),Y
	INY
	STA	SCNBUF,X	
	INX
	DEC	TMP_NMI1
	BNE	DP10
	STX	SCCNT
	RTS


DP100: 	LDA	NEW_PAL
	BEQ	DP200
	LDA	#0
	STA	NEW_PAL		;RESET FLAG, BOTH ARE INITIALIZED NOW

	LDY	#0
	LDA	(SPAL_BASE),Y
	STA	SPAL_BLINK	;SET BLINK FOR BACKGROUND
	INY
	LDA	(SPAL_BASE),Y
	STA	SPAL_DEPTH	;SET DEPTH OF BLINK
	INY
	LDA	#1
	STA	SPAL_INDX	;WE BOOT WITH BLINK 0, SO NEXT IS 1
	LDA	(SPAL_BASE),Y
	STA	SPAL_FREQ	;SET FREQUENCY
	STA	SPAL_CNT	;AND SET TIMER COUNT
	
	CLC
	LDA	SPAL_BASE
	ADC	#3
	STA	SPAL_BASE
	LDA	SPAL_BASE+1
	ADC	#0
	STA	SPAL_BASE+1	;POINT BASE DIRECTLY TO DATA

	LDX	SCCNT		;GET SCREEN BUFFER COUNT
	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	#H'3F
	STA	SCNBUF,X
	INX
	LDA	#H'11		;SKIP PAST THE LOWEST REG WHICH OVERLAPS WITH
	STA	SCNBUF,X	;THE BACKGROUND COLOR AND WOULD MESS IT UP.
	INX
	LDA	#15
	STA	SCNBUF,X		;QUE UP WRITE LOCATION AND COUNT
	INX
	STA	TMP_NMI1	;AND MAKE A LOOP COUNT
	LDY	#1

DP110:	LDA	(SPAL_BASE),Y
	INY
	STA	SCNBUF,X	
	INX
	DEC	TMP_NMI1
	BNE	DP110
	STX	SCCNT
	RTS			;AND DONE INITIALIZING PALETTE

		
DP200:	LDA	BPAL_BLINK
	BEQ	DP300
      	DEC	BPAL_CNT
	BNE	DP300		;IF IT BLINKS, TIME TO UPDATE PALETTE?
	LDA	BPAL_FREQ
	STA	BPAL_CNT	;IF SO, RELOAD COUNT

	LDA	BPAL_BLINK
	ASL	A
	ASL	A		;MAKE *4 NUMBER OF BYTES PER BLINK INFO
	STA	TMP_NMI1	;AND SAVE AS NUMBER OF BYTES TO WRITE OUT.
	TAX
	LDY	BPAL_INDX	;GET THE FRAME WE ARE DOING
	JSR	MUL		;MAKE OFFSET TO THE COLORS
	LDA	#16
	SEC
	SBC	TMP_NMI1	;MAKE POINTER TO FIRST BLINKING PALETTE
	STA	TMP_NMI2	;SAVE FOR LATER
	JSR	ADD_WORD 	;AND ADD DEPTH INTO THE BLINKING ARRAY
	STX	NMI_PTR
	STY	NMI_PTR+1
	LDA	BPAL_BASE
	CLC
	ADC	NMI_PTR
	STA	NMI_PTR
	LDA	BPAL_BASE+1
	ADC	NMI_PTR+1
	STA	NMI_PTR+1	;ADD BASE TO THE LOCATION WE WANT

	LDX	SCCNT		;POINT WITHIN BUFFER AT WHICH TO STORE
	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	#H'3F
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI2	;GET FIRST PAL REG TO UPDATE
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI1	;GET COUNT
	STA	SCNBUF,X
	INX

DP210:	LDA	(NMI_PTR),Y	;GET DATA
	STA	SCNBUF,X		;PUT IN BUFFER FOR UPDATE NEXT PASS
	INY
	INX
	DEC	TMP_NMI1	;DO THE NUMBER WE CALCULATED
	BNE	DP210
	STX	SCCNT		;UPDATE COUNT FOR NEXT PASS
	
	INC	BPAL_INDX	;UPDATE FOR NEXT TIME
	LDA	BPAL_INDX
	CMP	BPAL_DEPTH 	;SEE IF WENT TOO HIGH
	BNE	DP300
	LDA	#0
	STA	BPAL_INDX	;IF TOO HIGH, GO BACK TO 0


DP300: 	LDA	SPAL_BLINK
	BEQ	DP400
      	DEC	SPAL_CNT
	BNE	DP400		;IF IT BLINKS, TIME TO UPDATE PALETTE?
	LDA	SPAL_FREQ
	STA	SPAL_CNT

	LDA	SPAL_BLINK
	ASL	A
	ASL	A		;MAKE *4 NUMBER OF BYTES PER BLINK INFO
	STA	TMP_NMI1	;AND SAVE AS NUMBER OF BYTES TO WRITE OUT.
	TAX
	LDY	SPAL_INDX	;GET THE FRAME WE ARE DOING
	JSR	MUL		;MAKE OFFSET TO THE COLORS
	LDA	#16
	SEC
	SBC	TMP_NMI1	;MAKE POINTER TO FIRST BLINKING PALETTE
	STA	TMP_NMI2	;SAVE FOR LATER
	JSR	ADD_WORD	;AND ADD DEPTH INTO THE BLINKING ARRAY
	STX	NMI_PTR
	STY	NMI_PTR+1
	LDA	SPAL_BASE
	CLC
	ADC	NMI_PTR
	STA	NMI_PTR
	LDA	SPAL_BASE+1
	ADC	NMI_PTR+1
	STA	NMI_PTR+1	;ADD BASE TO THE LOCATION WE WANT


	LDX	SCCNT		;POINT WITHIN BUFFER AT WHICH TO STORE
	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	#H'3F
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI2	;GET FIRST PAL REG TO UPDATE
	CLC
	ADC	#H'10		;SPRITE REGS ARE HERE
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI1	;GET COUNT
	STA	SCNBUF,X
	INX

	LDY	#0		;SET RETRIEVE INDEX.  
DP310:	LDA	(NMI_PTR),Y	;GET DATA
	STA	SCNBUF,X		;PUT IN BUFFER FOR UPDATE NEXT PASS
	INY
	INX
	DEC	TMP_NMI1	;DO THE NUMBER WE CALCULATED
	BNE	DP310
	STX	SCCNT		;UPDATE COUNT FOR NEXT PASS
	
	INC	SPAL_INDX	;UPDATE FOR NEXT TIME
	LDA	SPAL_INDX
	CMP	SPAL_DEPTH 	;SEE IF WENT TOO HIGH
	BNE	DP400
	LDA	#0
	STA	SPAL_INDX	;IF TOO HIGH, GO BACK TO 0

DP400:	RTS



DOSCRL:	LDA	MOVEBACK
	BNE	DOS10
DOS5:	RTS			;IF FLAG NOT SET, NOTHING TO DO.

DOS10:	JSR	FIXSCROLL	;FIX THE USER'S SCROLL VARIABLES

IFDEF( `BLOCKMODE', `		
	LDA	DIDX
	BNE	DOS20
	LDA	#-1
	STA	DIDX
	JSR	DOXSCROLL
	JSR	DOYSCROLL
	RTS

DOS20:	LDA	#0
	STA	DIDX
	JSR	DOYSCROLL
	', )
	JSR	DOXSCROLL
	RTS


DOXSCROLL:
	LDA	MOVEBACK
	AND	#1		;X SCROLL NEEDED?
	BEQ	DOS55		;IF NOT, SKIP TO Y LOGIC
	
	LDA	#8
	STA	SCRLDIF		;SET FOR LOCATION CORRECTION OF 8.

 	LDA	CURX 		;GET CURRENT POSITION
	SEC
	SBC	XBACK		;MAKE DIFFERENCE TO NEW DIRECTION
	TAY
	LDA	CURX+1
	SBC	XBACK+1
	BCC	DOS30


DOS25:	BNE	DOS60		;IF HIGH DIFFERENCE NON-ZERO, IT IS A SCROLL
	TYA			;IF TOP BYTE 0, SEE IF LOW BYTE IS ZERO TOO
	BEQ	DOS50		;IF NO SCROLL NEEDED, RESET X SCROLL BIT
	CMP	#8		;SEE IF DIF 8 OR GREATER 
	BCS	DOS60		;ALWAYS SCROLL IF SO
	STA	SCRLDIF

	
	LDA	XBACK
	AND	#7
	STA	SUBSVAR1
	LDA	CURX
	AND	#7
	SEC
	SBC	SUBSVAR1	;SEE IF PASSED THROUGH 0
	BCS	DOS40
	JMP	DOS60		;IF WE DID, NEED NEW COL EVEN THOUGH <8


DOS30:	CMP	#H'FF		;SEE IF HIGH BYTE WAS MORE THAN -1
	BEQ	DOS35
	JMP	DOS100		;IF SO, DIFFERENCE WAS MORE THAN 8

DOS35:	TYA			;GET BACK LOW BYTE OF DIFFERENCE
	CMP	#H'F9		;SEE IF MORE THAN 8	
	BCC	DOS39		;IF SO, ALWAYS NEED SCROLL
	EOR	#H'FF
	ADC	#0		;MAKE THE ACTUAL DIFFERENCE IF <8
	STA	SCRLDIF		;SET AS SCROLL CORRECTION AMOUNT

	
	LDA	CURX
	AND	#7
	STA	SUBSVAR1
	LDA	XBACK
	AND	#7
	SEC
	SBC	SUBSVAR1	;SEE IF PASSED THROUGH 0
	BCS	DOS40
DOS39:	JMP	DOS100		;IF WE DID, NEED NEW COL EVEN THOUGH <8


DOS40:	LDA	XBACK
	STA	CURX
	LDA	XBACK+1
	STA	CURX+1


DOS50:	LDA	MOVEBACK
	AND	#H'FE		;TURN OFF X NEEDS SCROLLING BIT
	STA	MOVEBACK
DOS55:	RTS


DOS60: 	JSR	GET_ROOM	;GET FREE SPACE
	CMP	#80
	BCS	DOS70
	RTS		;IF NOT ENOUGH TO SCROLL, FORGET IT THIS PASS

DOS70:	JSR	ADJCURX		;MAKE CURRENT STARTING COL
	TXA
	SEC
	SBC	#1
	STA	FETCHCOL
	TYA
	SBC	#0
	STA	FETCHCOL+1	;MAKE FETCHCOL = 1 TO THE LEFT

	LDA	CURX
	SEC
	SBC	SCRLDIF
	STA	CURX
	LDA	CURX+1
	SBC	#0
	STA	CURX+1		;MOVE LEFT AMOUNT WE MADE EARLIER

	JSR	ADJCURY		;MAKE ROW TO START FROM
	STX	FETCHROW	;SAVE ROW HERE
	JSR	FINDCOL		;FIND THE COLUMN WITHIN THE BACKGROUND
	JSR	BUILD_COL	;MAKE DATA FOR THIS COLUMN
	JMP	DOS150		;AND DONE FOR NOW.  NEXT NMI WILL FIX PIXELS.


DOS100:	JSR	GET_ROOM	;GET FREE SPACE
	CMP	#80
	BCS	DOS105
	RTS			;IF NOT ENOUGH TO SCROLL, FORGET IT THIS PASS

DOS105:	JSR	ADJCURY		;MAKE CURRENT DATA ROW
	STX	FETCHROW

	JSR	ADJCURX		;MAKE CURRENT LOCATION INTO COLUMN #
	TXA	
	CLC
	ADC	#33		;POINT TO NEW COL TO WRITE OUT
	STA	FETCHCOL
	TYA
	ADC	#0
	STA	FETCHCOL+1	;MAKE FETCHCOL=1 TO RIGHT OF SCREEN

	LDA	FETCHCOL
	SEC
	SBC	WORLD_WIDTH
	LDA	FETCHCOL+1
	SBC	WORLD_WIDTH+1	;SEE IF PAST RIGHT
	BCS	DOS107
	
	JSR	FINDCOL
	JSR	BUILD_COL	;MAKE DATA FOR THIS COL

DOS107:	LDA	CURX		;GET CURRENT LOCATION
	CLC
	ADC	SCRLDIF
	STA	CURX
	LDA	CURX+1
	ADC	#0
	STA	CURX+1


DOS150:	RTS		


IFDEF( `BLOCKMODE', `		


DOYSCROLL:

	LDA	MOVEBACK
	AND	#2		;Y SCROLL NEEDED?
	BEQ	DYS55		;IF NOT, DONE

	LDA	#8
	STA	SCRLDIF		;SET FOR LOCATION CORRECTION OF 8.

 	LDA	CURY 		;GET CURRENT POSITION
	SEC
	SBC	YBACK		;MAKE DIFFERENCE TO NEW DIRECTION
	TAY
	LDA	CURY+1
	SBC	YBACK+1
	BCC	DYS30


DYS25:	BNE	DYS60		;IF HIGH DIFFERENCE NON-ZERO, IT IS A SCROLL
	TYA			;IF TOP BYTE 0, SEE IF LOW BYTE IS ZERO TOO
	BEQ	DYS50		;IF NO SCROLL NEEDED, RESET Y SCROLL BIT
	CMP	#8		;SEE IF DIF 8 OR GREATER 
	BCS	DYS60		;ALWAYS SCROLL IF SO
	STA	SCRLDIF

	
	LDA	YBACK
	AND	#7
	STA	SUBSVAR1
	LDA	CURY
	AND	#7
	SEC
	SBC	SUBSVAR1	;SEE IF PASSED THROUGH 0
	BCS	DYS40
	JMP	DYS60		;IF WE DID, NEED NEW COL EVEN THOUGH <8


DYS30:	CMP	#255		;SEE IF HIGH BYTE WAS MORE THAN -1
	BEQ	DYS35
	JMP	DYS100		;IF SO, DIFFERENCE WAS MORE THAN 8

DYS35:	TYA			;GET BACK LOW BYTE OF DIFFERENCE
	CMP	#249		;SEE IF MORE THAN 8	
	BCC	DYS39		;IF SO, ALWAYS NEED SCROLL
	EOR	#255
	ADC	#0		;MAKE THE ACTUAL DIFFERENCE IF <8
	STA	SCRLDIF		;SET AS SCROLL CORRECTION AMOUNT

	
	LDA	CURY
	AND	#7
	STA	SUBSVAR1
	LDA	YBACK
	AND	#7
	SEC
	SBC	SUBSVAR1	;SEE IF PASSED THROUGH 0
	BCS	DYS40
DYS39:	JMP	DYS100		;IF WE DID, NEED NEW COL EVEN THOUGH <8


DYS40:	LDA	YBACK
	STA	CURY
	LDA	YBACK+1
	STA	CURY+1


DYS50:	LDA	MOVEBACK
	AND	#253		;TURN OFF Y NEEDS SCROLLING BIT
	STA	MOVEBACK
DYS55:	RTS			;DONE


DYS60: 	JSR	GET_ROOM	;GET FREE SPACE
	CMP	#60
	BCS	DYS70
	RTS		;IF NOT ENOUGH TO SCROLL, FORGET IT THIS PASS

DYS70:	JSR	ADJCURY		;MAKE CURRENT STARTING ROW
	TXA
	SEC
	SBC	#1
	STA	FETCHROW

	LDA	CURY
	SEC
	SBC	SCRLDIF
	STA	CURY
	LDA	CURY+1
	SBC	#0
	STA	CURY+1		;MOVE LEFT AMOUNT WE MADE EARLIER

	JSR	ADJCURX		;MAKE COLUMN TO START FROM
	STX	FETCHCOL	;SAVE HERE
	STY	FETCHCOL+1
	JSR	FINDCOL		;FIND THE COLUMN WITHIN THE BACKGROUND
	JSR	BUILD_ROW	;MAKE DATA FOR THIS ROW
	JMP	DYS150		;AND DONE FOR NOW.  NEXT NMI WILL FIX PIXELS.


DYS100:	JSR	GET_ROOM	;GET FREE SPACE
	CMP	#60
	BCS	DYS105
	RTS			;IF NOT ENOUGH TO SCROLL, FORGET IT THIS PASS

DYS105:	JSR	ADJCURY		;MAKE CURRENT DATA ROW
	TXA
	CLC
	ADC	#30		;ADD 1 COLUMN TO BOTTOM
	STA	FETCHROW

	JSR	ADJCURX		;MAKE COLUMN TO START FROM
	STX	FETCHCOL	;SAVE HERE
	STY	FETCHCOL+1
	JSR	FINDCOL		;FIND THE COLUMN WITHIN THE BACKGROUND
	JSR	BUILD_ROW	;MAKE DATA FOR THIS ROW

	LDA	CURY		;GET CURRENT LOCATION
	CLC
	ADC	SCRLDIF
	STA	CURY
	LDA	CURY+1
	ADC	#0
	STA	CURY+1


DYS150:	RTS		

	', )


MAKE_SCROLL:
	LDA	BACKVALID	;MAKE SURE THERE IS A BACKGROUND TO USE
	BEQ	MKS20
	LDA	REG2000
	AND	#H'FE		;REMOVE OLD PAGE SELECT BIT
	STA	REG2000
	LDA	CURX+1
	AND	#1		;MAKE NEW ONE FROM BIT 9 OF X SCROLL
	ORA	REG2000
	STA	REG2000			
	LDA	CURX
	STA	XSCROLL		;AND USE THE ACTUAL SCROLL AS THE X SCROLL

	LDA	CURY
	CLC
	ADC	SHAKEAMT
	TAX
	LDA	CURY+1
	ADC	#0
	TAY
	LDA	#240
	JSR	DIVIDE		;FIND OUT WHERE TO PUT THE SCROLL MOD 1 SCREEN
	STY	YSCROLL
MKS20:	RTS			


BUILD_ROW:

IFDEF( `BLOCKMODE', `		

	LDA	WORLDSPOT
	STA	TMP_NMI9	
	LDA	WORLDSPOT+1
	STA	TMP_NMIA	;NEED COPY OF STARTING BACKGRND FOR PAL BYTES

IFDEF( `INDIRECT', `
 	LDA	#1		;SKIP 1 ONLY IF 1 BYTE BLOCK FORMAT
	', `
	LDA	#2		;IF WORD BLOCK MODE, 2 BYTES PER BLOCK SPEC
	' )
	STA	TMP_NMI3
	LDA	#0
	STA	TMP_NMI4	;MAKE 1 WORD CORRECTION TO NEXT BLOCK COLUMN


	LDA	FETCHCOL
	AND	#31		;MAKE SCREEN COLUMN WITHIN THE VIDEO PAGE
	STA	TMP_NMID	;SAVE TO MAKE AMOUNT WE CAN WRITE TO END

	LDX	#32		;ASSUME PAGE AT 2000H STARTS THE COLUMN
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BR20
	LDX	#36		;IF ODD BIT ABOVE WIDTH, PAGE 2

BR20:	STX	TMP_NMI8	;SAVE STARTING PAGE
	LDX	FETCHROW
	LDY	#0
	LDA	#30
	JSR	DIVIDE		;MAKE REMAINDER FROM MOD 30 (SCREEN HEIGHT)
	STX	TMP_NMIB	;SAVE PAGE WRAP WE ARE IN FOR SHIFT COUNT.
	STY	SUBSVAR6	;SAVE REMAINDER ROW HERE FOR PALETTE FIGURING
	LDX	#32
	JSR	MUL		;MAKE ROW WITHIN SCREEN BUFFER
	STX	TMP_NMI7	;SAVE ROW 0 LOCATION FOR NEXT PAGE WRITE
	TXA
	CLC
	ADC	TMP_NMID	;ADD TO GET COLUMN IN THIS VIDEO ROW AND PAGE
	STA	TMP_NMI5
	TYA
	ADC	TMP_NMI8
	STA	TMP_NMI6	
	TYA
	CLC
	ADC	TMP_NMI8
	EOR	#4		;MAKE NEXT PAGE ADDRESS AT COLUMN 0
	STA	TMP_NMI8
	', )
IFDEF( `BLOCKMODE', `		


	LDA	WORLD_WIDTH	;WE ALWAYS WRITE OUT 33
	SEC
	SBC	FETCHCOL	;MAKE DISTANCE TO RIGHT OF BACKGROUND
	STA	TMP_NMIE
	LDA	WORLD_WIDTH+1
	SBC	FETCHCOL+1
	BEQ	BR21
     	LDA	#-1
	STA	TMP_NMIE	;IF MORE THAN 256, USE MAX
BR21:	LDA	TMP_NMIE
	CMP	#33		;33 IS ALL WE WANT
	BCC	BR22
	LDA	#33		;IF MORE THAN THAT, JUST WRITE 33
BR22:	STA	TMP_NMIE	;SET HERE AS MAXIMUM WE COULD WRITE OUT

	LDA	#32
	SEC
	SBC	TMP_NMID	;MAKE DISTANCE TO RIGHT OF THIS VIDEO PAGE
	CMP	TMP_NMIE	;MAKE SURE THERES ENOUGH TO FILL TO BOTTOM
	BCC	BR24
     	LDA	TMP_NMIE	;IF NOT, USE HOW MUCH IS LEFT.
BR24:	STA	TMP_NMID	;SAVE AMOUNT TO BOTTOM OF THIS VIDEO PAGE
	LDA	TMP_NMIE	;GET TOTAL WE ARE WRITING
	SEC
	SBC	TMP_NMID	;MAKE INTO AMOUNT TO WRITE IN SECOND PAGE
	STA	TMP_NMIE	;AND SAVE HERE FOR LOOPING.


	JSR	ROWBACK		;MAKE (NMI_PTR) TO THE DATA AT ROW WE WANT
	LDA	FETCHCOL
	AND	#7		;GET COL WE ARE ON IN THIS BLOCK
	STA	TMP_NMIC	;SAVE A COPY
	CLC
	ADC	NMI_PTR
	STA	NMI_PTR
	BCC	BR28
	INC	NMI_PTR+1	;FOR FIRST ADDRESSING, START AT ODD ROW
BR28:	LDA	#8
	SEC
	SBC	TMP_NMIC	;MAKE AMOUNT LEFT IN THIS BACKGROUND.
	STA	TMP_NMIC	;PUT WHERE LOOP WANTS IT TO BE


	LDX	SCCNT		;GET THE INDEX
BR30:	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI6
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI5
	STA	SCNBUF,X
	INX

	LDA	TMP_NMID	
	STA	SCNBUF,X	;STORE THE COUNT TO WRITE FOR THE FIRST HALF
	INX


BR32: 	LDA	TMP_NMIC	;GET AMOUNT LEFT IN THIS BACKGROUND
	BNE	BR34		;IF THERE IS SOME, USE IT
	JSR	NEXTBACK	;SKIP TO THE NEXT BACKGROUND IN THE BLOCK
  	JSR	ROWBACK		;SET UP FOR NEW BACKGROUND
	LDA	#8
	STA	TMP_NMIC	;RESET AMOUNT WE CAN WRITE FROM THERE

BR34:	CMP	TMP_NMID	;DO WE NEED THAT MUCH?
	BCC	BR35
	LDA	TMP_NMID	;IF NOT, USE AS MUCH AS WE NEED
	BEQ	BR50		;IF NONE LEFT, DONE WITH THIS WRITE
BR35:	STA	TMP_NMI1	;SET UP TO FETCH THIS DATA
	LDA	TMP_NMIC
	SEC	
	SBC	TMP_NMI1	;MAKE AMOUNT LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	TMP_NMID
	SEC
	SBC	TMP_NMI1	;AND AMOUNT LEFT TO WRITE OUT WITH THIS ADDRESS
	STA	TMP_NMID
 
				;USES TMP_NMI1 = LENGTH
	JSR	LOADROW		;AND (NMI_PTR) = DATA.  X=PLACE IN SCNBUF.
	JMP	BR32		;KEEP WRITING TILL TMP_NMID IS DONE


BR50:	LDA	TMP_NMIE
	BEQ	BR100
	STA	TMP_NMID
	LDA	#0
	STA	TMP_NMIE	;ZERO SECOND WRITE FOR NEXT PASS

	LDA	TMP_NMI7
	STA	TMP_NMI5
	LDA	TMP_NMI8
	STA	TMP_NMI6
	JMP	BR30		;GO SHARE ADDRESS AND LENGTH CODE

	', )
IFDEF( `BLOCKMODE', `		


BR100:	STX	SCCNT		;SAVE THE COUNT WE WROTE


	LDA	SUBSVAR6	;GET ROW WITHIN SCREEN BUFFER
	AND	#2		;THIS IS THE DESTINGUISHING VALUE
	BEQ	BR101
	JMP	BR400	


BR101:	LDA	#0
	STA	WORLDSPOT
	STA	WORLDSPOT+1	;ASSUME NO BACKUP CORRECTION NEEDED

	LDA	TMP_NMIB	;GET BACK PAGE WE ARE IN
	AND	#1
	BEQ	BR110

	LDA	FETCHROW
	AND	#7		;GET WHAT ROW WITHIN THE 8 HIGH BACKGROUND
	CMP	#2
	BCS	BR105		

 	LDA	BLOCK_WIDTH	;IF ROW 0 OR 1, WE NEED TO BACK UP A BACKGRND
	STA	WORLDSPOT

BR105:	LDA	FETCHROW
	SEC
	SBC	#2
	STA	FETCHROW	;MOVE UP 2 ROWS SO ROWPAL CAN GET THE DATA

IFDEF( `INDIRECT', `
			;NO CORRECTION IF 1 BYTE TABLE FORMAT
	', `
	ASL	WORLDSPOT
	ROL	WORLDSPOT+1	;MAKE 1 WORD CORRECTION TO NEXT BLOCK ROW
	' )

BR110:	LDA	TMP_NMI9
	SEC
	SBC	WORLDSPOT
	STA	WORLDSPOT
	LDA	TMP_NMIA
	SBC	WORLDSPOT+1
	STA	WORLDSPOT+1	;POINT TO NEXT BLOCK ROW IF NEEDED.


	LDX	#35		;ASSUME PAGE AT 23C0H STARTS THE COLUMN
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BR120

	LDX	#39		;IF ODD BIT ABOVE WIDTH, PAGE 2 AT 27C0H

BR120:	STX	TMP_NMI8	;SAVE STARTING PAGE

	LDA	SUBSVAR6	;GET REMAINDER WITHIN THIS SCREEN BUFFER
	AND	#252		;REMOVE LOW 2 BITS TO MAKE EVERY 4 COUNT
	ASL	A		;AND MULTIPLY BY 2 CAUSE 8 PER ROW IN PAL BUF
	CLC
	ADC	#192		;ADD C0H  TO GET THIS ROWS BASE
	STA	TMP_NMI7	;SAVE ROW 0 LOCATION IN BUFFER.

	LDA	FETCHCOL	;GET COLUMN WE ARE ON
	AND	#31		;IN THIS BUFFER
	LSR	A
	LSR	A		;MAKE PALETTE BYTE WE ARE ON
	CLC
	ADC	TMP_NMI7	;ADD TO GET COLUMN IN THIS PALETTE VIDEO PAGE
	STA	TMP_NMI5
	LDA	TMP_NMI8
	STA	TMP_NMI6	;MAKE 6 AND 5 BE ADDRESS IN FIRST PAGE

	LDA	TMP_NMI8
	EOR	#4		;MAKE NEXT PAGE ADDRESS AT COLUMN 0
	STA	TMP_NMI8	;SO 7 AND 8 POINT TO COLUMN 0 OF NEXT PAGE
	', )
IFDEF( `BLOCKMODE', `		


	LDA	FETCHCOL
	AND	#31
	LSR	A
	LSR	A		;MAKE PALETTE BYTE IN BUFFER
	JSR	NEGATE
	CLC
	ADC	#8		;MAKE DISTANCE TO END
	STA	TMP_NMID	;SET FIRST WRITE AMOUNT

	LDA	#9		;IF NOT ON LAST COLUMN WE ALWAYS WRITE 9
	STA	TMP_NMIE
	LDA	END_COL
	SEC
	SBC	FETCHCOL	
	BNE	BR121
      	LDA	END_COL+1
	SBC	FETCHCOL+1
	BNE	BR121
	DEC	TMP_NMIE	;IF AT EXACT END, WRITE OUT 8 ONLY.

BR121:	LDA	TMP_NMIE
	SEC
	SBC	TMP_NMID	;MAKE AMOUNT FOR SECOND PAGE WRITE
	STA	TMP_NMIE


	JSR	ROWPAL		;MAKE (NMI_PTR) TO THE DATA AT ROW WE WANT

	LDA	#2		;ASSUME 2 LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	FETCHCOL
	AND	#4		;SEE IF WE ARE IN THE SECOND PALETTE BYTE
	BEQ	BR128
	DEC	TMP_NMIC	;IF SO, ONLY 1 LEFT IN THIS BACK
	INC	NMI_PTR
	BNE	BR128
	INC	NMI_PTR+1	;AND WE NEED SECOND PALETTE BYTE


BR128:	LDX	SCCNT		;GET THE INDEX

BR130:	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI6
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI5
	STA	SCNBUF,X
	INX

	LDA	TMP_NMID	
	STA	SCNBUF,X	;STORE THE COUNT TO WRITE FOR THE FIRST HALF
	INX

	', )
IFDEF( `BLOCKMODE', `		


BR132: 	LDA	TMP_NMIC	;GET AMOUNT LEFT IN THIS BACKGROUND
	BNE	BR134		;IF THERE IS SOME, USE IT
	JSR	NEXTBACK	;SKIP TO THE NEXT BACKGROUND IN THE BLOCK
  	JSR	ROWPAL		;SET UP FOR NEW BACKGROUND
	LDA	#2
	STA	TMP_NMIC	;RESET AMOUNT WE CAN WRITE FROM THERE

BR134:	CMP	TMP_NMID	;DO WE NEED THAT MUCH?
	BCC	BR135
	LDA	TMP_NMID	;IF NOT, USE AS MUCH AS WE NEED
	BEQ	BR150		;IF NONE LEFT, DONE WITH THIS WRITE
BR135:	STA	TMP_NMI1	;SET UP TO FETCH THIS DATA
	LDA	TMP_NMIC
	SEC	
	SBC	TMP_NMI1	;MAKE AMOUNT LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	TMP_NMID
	SEC
	SBC	TMP_NMI1	;AND AMOUNT LEFT TO WRITE OUT WITH THIS ADDRESS
	STA	TMP_NMID
 
				;USES TMP_NMI1 = LENGTH
	JSR	LOADROW		;AND (NMI_PTR) = DATA.  X=PLACE IN SCNBUF.
	JMP	BR132		;KEEP WRITING TILL TMP_NMID IS DONE


BR150:	LDA	TMP_NMIE
	BEQ	BR200
	STA	TMP_NMID
	LDA	#0
	STA	TMP_NMIE	;ZERO SECOND WRITE FOR NEXT PASS

	LDA	TMP_NMI7
	STA	TMP_NMI5
	LDA	TMP_NMI8
	STA	TMP_NMI6
	JMP	BR130		;GO SHARE ADDRESS AND LENGTH CODE


BR200:	LDA	TMP_NMIB	;GET BACK PAGE WE ARE IN
	AND	#1
	BNE	BR210
	JMP	BR400		;IF EVEN PAGE, DATA IS CORRECT.


BR210:	STX	TMP_NMI5	;SAVE RESULTING END POSITION

	LDA	FETCHROW
	CLC
	ADC	#2		;PUT FETCHING ROW BACK TO CORRECT VALUE
	STA	FETCHROW

	LDA	#0
	STA	WORLDSPOT
	STA	WORLDSPOT+1	;ASSUME WE HAVE TO MOVE DOWN A BACKGROUND
	LDA	FETCHROW
	AND	#7		;WE DO IF WE ARE ON THE LAST PALETTE ROW
	CMP	#6
	BCC	BR211
 	LDA	BLOCK_WIDTH
	STA	WORLDSPOT	;THE BYTE WE WANT IS IN THE NEXT BACKGROUND.

BR211:

IFDEF( `INDIRECT', `
			;NO CORRECTION IF 1 BYTE TABLE FORMAT
	', `
	ASL	WORLDSPOT
	ROL	WORLDSPOT+1	;MAKE 1 WORD CORRECTION TO NEXT BLOCK ROW
	' )

	LDA	TMP_NMI9
	CLC
	ADC	WORLDSPOT
	STA	WORLDSPOT
	LDA	TMP_NMIA
	ADC	WORLDSPOT+1
	STA	WORLDSPOT+1	;POINT TO NEXT BLOCK ROW IF NEEDED.

	LDA	FETCHROW
	CLC
	ADC	#2
	STA	FETCHROW	;MOVE OUR POINTER AHEAD.

	', )
IFDEF( `BLOCKMODE', `		


	LDA	SCCNT		;GET ORIGINAL POINTER
	CLC
	ADC	#4		;SKIP THE HEADER, POINT TO DATA WE PUT THERE
	STA	TMP_NMI7	;SET AS FIRST PLACE TO WRITE DATA
	TAX
	DEX			;GET LENGTH BYTE
	LDA	SCNBUF,X
	STA	TMP_NMID	;SAVE COUNT
	CLC
	ADC	TMP_NMI7	;AND SKIP THAT TO POINT TO NEXT DATA
	ADC	#4		;ALSO SKIP THAT HEADER
	STA	TMP_NMI8	;MAKE IN CASE OF SECOND WRITE
	CMP	TMP_NMI5	;SEE IF WE DID WRITE A SECOND TIME.
	BCS	BR213		;TMP_NMIE=0 FROM BEFORE SO WE CAN SKIP IF NOT
  	TAX			
	DEX
	LDA	SCNBUF,X
	STA	TMP_NMIE	;SET AMOUNT WE WROTE SECOND PASS


BR213:	JSR	ROWPAL		;MAKE (NMI_PTR) TO THE DATA AT ROW WE WANT

	LDA	#2		;ASSUME 2 LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	FETCHCOL
	AND	#4		;SEE IF WE ARE IN THE SECOND PALETTE BYTE
	BEQ	BR228
	DEC	TMP_NMIC	;IF SO, ONLY 1 LEFT IN THIS BACK
	INC	NMI_PTR
	BNE	BR228
	INC	NMI_PTR+1	;AND WE NEED SECOND PALETTE BYTE

BR228:	LDX	TMP_NMI7	;FOR THE FIRST PASS WE USE THIS LOCATION


BR232: 	LDA	TMP_NMIC	;GET AMOUNT LEFT IN THIS BACKGROUND
	BNE	BR234		;IF THERE IS SOME, USE IT
	JSR	NEXTBACK	;SKIP TO THE NEXT BACKGROUND IN THE BLOCK
  	JSR	ROWPAL		;SET UP FOR NEW BACKGROUND
	LDA	#2
	STA	TMP_NMIC	;RESET AMOUNT WE CAN WRITE FROM THERE

BR234:	CMP	TMP_NMID	;DO WE NEED THAT MUCH?
	BCC	BR235
	LDA	TMP_NMID	;IF NOT, USE AS MUCH AS WE NEED
	BEQ	BR250		;IF NONE LEFT, DONE WITH THIS WRITE
BR235:	STA	TMP_NMI1	;SET UP TO FETCH THIS DATA
	LDA	TMP_NMIC
	SEC	
	SBC	TMP_NMI1	;MAKE AMOUNT LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	TMP_NMID
	SEC
	SBC	TMP_NMI1	;AND AMOUNT LEFT TO WRITE OUT WITH THIS ADDRESS
	STA	TMP_NMID
 
	JSR	SHIFTROW	
	JMP	BR232		;KEEP WRITING TILL TMP_NMID IS DONE


BR250:	LDA	TMP_NMIE
	BEQ	BR400
	STA	TMP_NMID
	LDA	#0
	STA	TMP_NMIE	;ZERO SECOND WRITE FOR NEXT PASS

	LDX	TMP_NMI8
	JMP	BR232		;GO BACK AND DO ANOTHER BUNCH


BR400:	STX	SCCNT		;SAVE THE COUNT WE WROTE
 	RTS

	', )
IFDEF( `BLOCKMODE', `		


ROWBACK:		
	LDA	FETCHROW
	AND	#7
	ASL	A
	ASL	A
	ASL	A		;MAKE *8
	JMP	FINISH_COL


ROWPAL:		
	LDA	FETCHROW
	AND	#4		;SECOND PALETTE ROW IS FOR ROW 4 IN BACKGROUND
	LSR	A		;BUT THAT ONLY SKIPS 2 BYTES
	CLC
	ADC	#64
	JMP	FINISH_COL

	', )


BUILD_COL:

IFDEF( `BLOCKMODE', `		


	LDA	WORLDSPOT
	STA	TMP_NMI9	
	LDA	WORLDSPOT+1
	STA	TMP_NMIA	;NEED COPY OF STARTING BACKGRND FOR PAL BYTES

	LDA	BLOCK_WIDTH
	STA	TMP_NMI3
	LDA	#0
	STA	TMP_NMI4

IFDEF( `INDIRECT', `
			;NO CORRECTION IF 1 BYTE TABLE FORMAT
	', `
	ASL	TMP_NMI3
	ROL	TMP_NMI4	;MAKE 1 WORD CORRECTION TO NEXT BLOCK ROW
	' )


	LDA	FETCHCOL
	AND	#31		;MAKE SCREEN COLUMN WITHIN THE VIDEO PAGE
	STA	TMP_NMI7

	LDX	#32		;ASSUME PAGE AT 2000H STARTS THE COLUMN
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BC20
	LDX	#36		;IF ODD BIT ABOVE WIDTH, PAGE 2

BC20:	STX	TMP_NMI8	;SAVE STARTING PAGE
	LDX	FETCHROW
	LDY	#0
	LDA	#30
	JSR	DIVIDE		;MAKE REMAINDER FROM MOD 30 (SCREEN HEIGHT)
	STX	TMP_NMIB	;SAVE PAGE WRAP WE ARE IN FOR SHIFT COUNT.
	STY	TMP_NMID	;SAVE REMAINDER FOR COUNT WE CAN WRITE TO BOTTOM
	STY	SUBSVAR6	;SAVE HERE FOR PALETTE FIGURING
	LDX	#32
	JSR	MUL		;MAKE ROW WITHIN SCREEN BUFFER
	TXA
	CLC
	ADC	TMP_NMI7
	STA	TMP_NMI5
	TYA
	ADC	TMP_NMI8
	STA	TMP_NMI6	

	', )
IFDEF( `BLOCKMODE', `		


	LDA	WORLD_HEIGHT
	SEC
	SBC	FETCHROW	;MAKE DISTANCE TO BOTTOM OF BACKGROUND
	CMP	#30
	BCC	BC23
     	LDA	#30		;BUT WE ONLY CAN FIT 30 IN A SCREEN
BC23:	STA	TMP_NMIE	;SET HERE AS MAXIMUM WE COULD WRITE OUT
	LDA	#30
	SEC
	SBC	TMP_NMID	;MAKE DISTANCE TO BOTTOM OF THIS VIDEO PAGE
	CMP	TMP_NMIE	;MAKE SURE THERES ENOUGH TO FILL TO BOTTOM
	BCC	BC24
     	LDA	TMP_NMIE	;IF NOT, USE HOW MUCH IS LEFT.
BC24:	STA	TMP_NMID	;SAVE AMOUNT TO BOTTOM OF THIS VIDEO PAGE
	LDA	TMP_NMIE	;GET TOTAL WE ARE WRITING
	SEC
	SBC	TMP_NMID	;MAKE INTO AMOUNT TO WRITE IN SECOND PAGE
	STA	TMP_NMIE	;AND SAVE HERE FOR LOOPING.


	JSR	COLBACK		;MAKE (NMI_PTR) TO THE DATA AT COLUMN WE WANT
	LDA	FETCHROW
	AND	#7		;GET ROW WE ARE ON IN THIS BLOCK
	STA	TMP_NMIC	;SAVE A COPY
	ASL	A
	ASL	A
	ASL	A
	CLC
	ADC	NMI_PTR
	STA	NMI_PTR
	BCC	BC28
	INC	NMI_PTR+1	;FOR FIRST ADDRESSING, START AT ODD ROW
BC28:	LDA	#8
	SEC
	SBC	TMP_NMIC	;MAKE AMOUNT LEFT IN THIS BACKGROUND.
	STA	TMP_NMIC	;PUT WHERE LOOP WANTS IT TO BE


	LDX	SCCNT		;GET THE INDEX
BC30:	LDA	#4
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI6
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI5
	STA	SCNBUF,X
	INX

	LDA	TMP_NMID	
	STA	SCNBUF,X	;STORE THE COUNT TO WRITE FOR THE FIRST HALF
	INX

BC32: 	LDA	TMP_NMIC	;GET AMOUNT LEFT IN THIS BACKGROUND
	BNE	BC34		;IF THERE IS SOME, USE IT
	JSR	NEXTBACK	;SKIP TO THE NEXT BACKGROUND IN THE BLOCK
  	JSR	COLBACK		;SET UP FOR NEW BACKGROUND
	LDA	#8
	STA	TMP_NMIC	;RESET AMOUNT WE CAN WRITE FROM THERE

BC34:	CMP	TMP_NMID	;DO WE NEED THAT MUCH?
	BCC	BC35
	LDA	TMP_NMID	;IF NOT, USE AS MUCH AS WE NEED
	BEQ	BC50		;IF NONE LEFT, DONE WITH THIS WRITE
BC35:	STA	TMP_NMI1	;SET UP TO FETCH THIS DATA
	LDA	TMP_NMIC
	SEC	
	SBC	TMP_NMI1	;MAKE AMOUNT LEFT IN THIS BACKGROUND
	STA	TMP_NMIC
	LDA	TMP_NMID
	SEC
	SBC	TMP_NMI1	;AND AMOUNT LEFT TO WRITE OUT WITH THIS ADDRESS
	STA	TMP_NMID
 
	LDA	#8
	STA	TMP_NMI2	;USES TMP_NMI1 = LENGTH, TMP_NMI2 = WIDTH
	JSR	LOADCOL		;AND (NMI_PTR) = DATA.  X=PLACE IN SCNBUF.
	JMP	BC32		;KEEP WRITING TILL TMP_NMID IS DONE


BC50:	LDA	TMP_NMIE
	BEQ	BC100
	STA	TMP_NMID
	LDA	#0
	STA	TMP_NMIE	;ZERO SECOND WRITE FOR NEXT PASS

	LDA	TMP_NMI7
	STA	TMP_NMI5
	LDA	TMP_NMI8
	STA	TMP_NMI6
	JMP	BC30		;GO SHARE ADDRESS AND LENGTH CODE

	', )
IFDEF( `BLOCKMODE', `		


BC100:	STX	SCCNT		;SAVE THE COUNT WE WROTE

	LDA	TMP_NMI9
	STA	WORLDSPOT
	LDA	TMP_NMIA
	STA	WORLDSPOT+1	;POINT BACK TO THE FIRST BLOCK WE USED
	LDA	TMP_NMIB
	AND	#1
	STA	TMP_NMI2	;SAVE THE SHIFT FLAG HERE.  ODD SCREENS SHIFT


	LDA	WORLD_HEIGHT
	SEC
	SBC	FETCHROW	;MAKE DISTANCE TO BOTTOM OF BACKGROUND
	CMP	#36		;SEE IF TOO MUCH.  WE CAN ONLY FETCH 9 MAX.
	BCC	BC110
	LDA	#36		;IF SO, WE WOULD HAVE FETCHED 30 ONLY
BC110:	CLC
	ADC	#3		;ROUND IT UP IN CASE OF ODD AMOUNT
	LSR	A
	LSR	A		;DIVIDE BY 4 TO GET NUMBER OF PALETTE BYTES
	STA	TMP_NMI5	;SAVE BYTES TO FETCH HERE.
	STA	SUBSVAR5	;AND OUT OF VARIABLES SO SAVE A COPY HERE.

	LDA	#2		;ASSUME FETCHING 2 FROM FIRST BACKGROUND
	STA	TMP_NMI1	;PUT IT HERE FOR THE CALL
	JSR	INPAL		;POINT TO THE PALETTE BYTE IF AT TOP

	LDA	TMP_NMI2	;SEE IF WE ARE GOING TO SHIFT THE BACKGROUND
	BEQ	BC111
      	LDA	FETCHROW
	AND	#2		;IF SO, ARE WE ON SECOND HALF OF A PAL BYTE?
	BNE	BC111		;IF SO, SHIFT IS OK. IF NOT, WE NEED PREV BYTE
	LDA	FETCHROW
	AND	#4
	BNE	BC115		;JUST USE FIRST PAL BYTE IF WE ARE ON SECOND
	JSR	PREVBACK	;IF ON FIRST, BACK UP TO LAST BACKGROUND
	JSR	INPAL
	JMP	BC112		;AND GET SECOND BYTE OF IT.

BC111: 	LDA	FETCHROW	;SEE IF ON SECOND ROW OF PALETTE ROWS
	AND	#4
	BEQ	BC115
BC112: 	LDA	#1		;IF SO, WE ARE FETCHING ONLY 1
	STA	TMP_NMI1
	LDA	NMI_PTR
	CLC
	ADC	#2
	STA	NMI_PTR
	BCC	BC115
	INC	NMI_PTR+1	;AND WE MUST SKIP THE FIRST ROW IN PAL BUFFER

BC115:	LDX	#0		;GET THE BYTES INTO BUFFER TMP_NMI6

BC120:	LDA	TMP_NMI5	;GET BYTES REMAINING TO FETCH
	BEQ	BC130
	SEC
	SBC	TMP_NMI1	;SUBTRACT NUMBER WE ARE GETTING NOW
	STA	TMP_NMI5
	JSR	LOADPCOL	;GETS DATA INTO TMP_NMI6,X FOR LENGTH TMP_NMI1
				;AT LOCATION X IN TMP_NMI6.
	JSR	NEXTBACK
  	JSR	INPAL		;SET UP FOR NEW BACKGROUND
	LDA	#2
	STA	TMP_NMI1	;SET AMOUNT TO FETCH NEXT TIME TO 2
	CMP	TMP_NMI5	;MAKE SURE ITS NOT MORE THAN WE NEED
	BCC	BC120
	LDA	TMP_NMI5
	STA	TMP_NMI1	;IF WE WERE GETTING TOO MANY, GET MAX
	JMP	BC120


BC130:	LDA	TMP_NMI2	;GET SHIFT FLAG
	BEQ	BC140
	LDY	#4		;MUST SHIFT 4 BITS DOWN
BC132:	CLC	
	ROR	TMP_NMIE
	ROR	TMP_NMID
	ROR	TMP_NMIC
	ROR	TMP_NMIB
	ROR	TMP_NMIA
	ROR	TMP_NMI9
	ROR	TMP_NMI8
	ROR	TMP_NMI7
	ROR	TMP_NMI6
	DEY
	BNE	BC132


BC140: 	LDA	SUBSVAR6
	AND	#3
	BNE	BC145		;IF NOT EXACTLY AT START OF BUFFER, ITS A SPLIT
	LDA	SUBSVAR5	;GET BACK NUMBER WE WROTE
	CMP	#8
	BCC	BC145
	LDA	#8
	STA	SUBSVAR5	;IF MORE THAN 8, JUST USE 8

	', )
IFDEF( `BLOCKMODE', `		


BC145:	LDA	FETCHCOL	;GET COLUMN WITHIN BUFFER
	AND	#31
	LSR	A
	LSR	A		;DIVIDE BY 4 TO FIND BYTE IN PALETTE ROW
	STA	TMP_NMI3	;SAVE ADDRESS OF COLUMN HERE
	LDA	SUBSVAR6	;GET ROW WITHIN VIDEO PAGE
	AND	#252		;REMOVE LOW 2 BITS
	ASL	A		;TO MAKE EVERY 4 ROWS SKIP 8 BYTES IN PAL RAM
	ADC	TMP_NMI3
	ADC	#192		;ADD HEX C0 CAUSE PALETTE STUFF STARTS THERE
	STA	TMP_NMI3	

	LDX	#35		;ASSUME PAGE 0 PALETTE ADDRESS
	
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BC150
	LDX	#39		;IF ODD BIT ABOVE WIDTH, PAGE 1

BC150:	STX	TMP_NMI4	;SAVE STARTING PAGE

	LDX	SCCNT
 	LDY	#0		;GET FIRST BYTE AT TMP_NMI6 FOR LEN SUBSVAR5
BC160:	LDA	#0
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI4
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI3
	STA	SCNBUF,X
	INX
	LDA	#1		;WE ALWAYS JUST QUE 1 IN THIS CASE
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI6,Y	;GET NEXT PALETTE BYTE
	INY
	STA	SCNBUF,X	;QUE IT UP
	INX
	LDA	TMP_NMI3	;SKIP TO NEXT PALETTE ROW
	CLC
	ADC	#8
	ORA	#192		;KEEP C0 SET IN CASE OF WRAP
	STA	TMP_NMI3
	BCC	BC170
	TYA
	PHA
 	LDY	#4     	
BC165:	CLC	     		;IF BUFFER WRAP, NEED TO SHIFT THE NIBBLES
	ROL	TMP_NMI6	;BACK UP CAUSE THE LAST ONE WAS THROWN
	ROL	TMP_NMI7	;OUT BY THE HARDWARE.
	ROL	TMP_NMI8
	ROL	TMP_NMI9
	ROL	TMP_NMIA
	ROL	TMP_NMIB
	ROL	TMP_NMIC
	ROL	TMP_NMID
	ROL	TMP_NMIE
	DEY
	BNE	BC165
	PLA
	TAY
BC170:	DEC	SUBSVAR5	;COUNT 1 MORE QUED UP
	BNE	BC160	
	STX	SCCNT		;SET COUNT WE STORED


 	RTS

	', )

IFDEF( `BLOCKMODE', `		

COLBACK:		
	LDA	FETCHCOL
	AND	#7

FINISH_COL:

	PHA
	TXA
	PHA
	LDA	WORLDSPOT
	STA	SUBSVAR1
	LDA	WORLDSPOT+1
	STA	SUBSVAR2
	JSR	GETWORD
	PLA
	TAX
	PLA
	LDY	#0

IFDEF( `INDIRECT', `
	PHA

	LDA	SUBSVAR1	;IF INDIRECT, THIS IS 1 BYTE OFFSET IN BLOCKS

	STA	NMI_PTR
	LDA	#0
	STA	NMI_PTR+1
	ASL	NMI_PTR
	ROL	NMI_PTR+1	;MAKE BLOCK POINTER
	LDA	#BLOCKS & 255
	CLC
	ADC	NMI_PTR
	STA	NMI_PTR
	LDA	#BLOCKS >> 8
	ADC	NMI_PTR+1
	STA	NMI_PTR+1
	PLA
	CLC
	ADC	(NMI_PTR),Y
	PHA
	INY
	LDA	(NMI_PTR),Y
	ADC	#0
	STA	NMI_PTR+1
	PLA
	STA	NMI_PTR
	', `

	ADC	SUBSVAR1	;IF WORD BLOCK MODE THEN THIS POINTS TO 

	STA	NMI_PTR		;THE BACKGROUND OFFSET
	TYA
	INY

	ADC	SUBSVAR2

	STA	NMI_PTR+1	;MAKE DIRECT POINTER TO THE DATA WE WANT
	' )

	RTS


INPAL:
	LDA	FETCHCOL
	ROR	A
	ROR	A
	ROR	A		;SET CARRY IF PAST FIRST PALETTE BYTE
	LDA	#64

	ADC	#0
	JMP	FINISH_COL



NEXTBACK:
	LDA	WORLDSPOT	;NOW POINT TO NEXT BACKGROUND
	CLC
	ADC	TMP_NMI3
	STA	WORLDSPOT
	LDA	WORLDSPOT+1
	ADC	TMP_NMI4
	STA	WORLDSPOT+1	;SKIP TO NEXT BLOCK
	RTS


PREVBACK:
	LDA	WORLDSPOT	;NOW POINT TO NEXT BACKGROUND
	SEC
	SBC	TMP_NMI3
	STA	WORLDSPOT
	LDA	WORLDSPOT+1
	SBC	TMP_NMI4
	STA	WORLDSPOT+1	;SKIP TO NEXT BLOCK
	RTS
	' , )

IFDEF( `BLOCKMODE', , `		


	LDA	SUBSVAR6	;GET COLUMN IN CURRENT BACKGROUND
	CLC
	ADC	BACKBASE
	STA	NMI_PTR
	LDA	#0
	ADC	BACKBASE+1
	STA	NMI_PTR+1	;POINT TO THE DATA WITH INDIRECT REG


	LDA	FETCHCOL
	AND	#31		;MAKE SCREEN COLUMN MOD WIDTH
	STA	TMP_NMI3	

	LDX	#32		;ASSUME PAGE AT 2000H STARTS THE COLUMN
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BC20
	LDX	#36		;IF ODD BIT ABOVE WIDTH, PAGE 2

BC20:	STX	TMP_NMI4	;SAVE STARTING PAGE


	LDX	SCCNT		;GET THE INDEX
	LDA	#4
	STA	SCNBUF,X	;SET HORIZONTAL/VERTICAL WRITE FLAG
	INX
	LDA	TMP_NMI4
	STA	SCNBUF,X
	INX
	LDA	TMP_NMI3
	STA	SCNBUF,X
	INX


	LDA	#30		;GET MAX HEIGHT WE CAN WRITE
	CMP	BACKHIGH	;SEE IF THERE REALLY IS THAT MUCH
	BCC	BC30
     	LDA	BACKHIGH	;IF NOT, WRITE OUT MAX
BC30:	STA	SCNBUF,X
	INX
	STA	TMP_NMI1	;SET COUNT TO WRITE OUT


	LDA	BACKWIDE
	STA	TMP_NMI2	;SET WIDTH FOR THE CALL
	JSR	LOADCOL
 	STX	SCCNT		;SAVE OFFSET IN BUFFER


	LDA	SUBSVAR6	;GET COL WE ARE ON
	LSR	A
	LSR	A		;MAKE PALETTE BYTE IN THAT COLUMN WE ARE ON
	CLC
	ADC	BPBASE
	STA	NMI_PTR
	LDA	BPBASE+1
	ADC	#0
	STA	NMI_PTR+1	;POINT TO THE DATA WITH INDIRECT REG

	' )

IFDEF( `BLOCKMODE', , `		


	LDA	TMP_NMI3	;GET BACK COL WITHIN SCREEN
	LSR	A
	LSR	A		;AND MAKE INTO PALETTE BYTE
	CLC
	ADC	#192		;ADD LOW OFFSET TO IT
	STA	TMP_NMI3	;SAVE BYTE IN PALETTE BUFFER

	LDX	#35		;ASSUME PAGE 0 PALETTE ADDRESS
	
	LDA	#32
	AND	FETCHCOL	;TEST TO GET PAGE NUMBER 
	BEQ	BC40
	LDX	#39		;IF ODD BIT ABOVE WIDTH, PAGE 1

BC40:	STX	TMP_NMI4	;SAVE STARTING PAGE


	LDA	BACKHIGH
	CLC
	ADC	#3		;ROUND UP HEIGHT IN ROWS
	LSR	A
	LSR	A		;MAKE HEIGHT IN PALETTE BYTES
	STA	TMP_NMI1	;SAVE HERE	
	LDA	#8		;GET HEIGHT IF FULL SCREEN.
	CMP	TMP_NMI1	;SEE IF WE CAN DO IT
	BCC	BC50		;IF THERE ARE ENOUGH, OK
	LDA	TMP_NMI1
BC50:	STA	TMP_NMI1
	LDA	BPWIDE
	STA	TMP_NMI2	

	LDX	SCCNT		;GET THE INDEX
	JSR	LOADPCOL	;QUE THE DATA
	STX	SCCNT		;UPDATE COUNT IN BUFFER


 	RTS

	' )


GET_ROOM:
	LDA	#SCSIZE
	SEC
	SBC	SCCNT
	RTS


FIXSCROLL:

 	LDA	RIGHTLIMIT
	SEC
	SBC	XBACK
	LDA	RIGHTLIMIT+1	
	SBC	XBACK+1		;SEE IF XBACK IS TOO BIG
	BCS	FX6
	LDA	RIGHTLIMIT
	STA	XBACK
	LDA	RIGHTLIMIT+1
	STA	XBACK+1		;IF TOO BIG, SET AS LAST POSITION

FX6:	LDA	BOTLIMIT
	SEC
	SBC	YBACK
	LDA	BOTLIMIT+1	
	SBC	YBACK+1		;SEE IF XBACK IS TOO BIG
	BCS	FX7
	LDA	BOTLIMIT
	STA	YBACK
	LDA	BOTLIMIT+1
	STA	YBACK+1		;IF TOO BIG, SET AS LAST POSITION

	JSR	MAKEDING

FX7:	RTS



ADJCURX:
	LDX	CURX
	LDY	CURX+1
DIV8XY:
ADJ_BACK:
	JSR	SHIFTDOWN
	JSR	SHIFTDOWN
	JMP	SHIFTDOWN

ADJCURY:			;TO GET AND ADJUST CURY.
	LDX	CURY
	LDY	CURY+1
	JMP	ADJ_BACK	


BACK_PIX:
	JSR	SHIFTUP
	JSR	SHIFTUP
	JMP	SHIFTUP


SHIFTDOWN:
	TYA
	LSR	A
	TAY
	TXA
	ROR	A
	TAX
	RTS


SHIFTUP:	
	TXA
	ASL	A
	TAX
	TYA
	ROL	A
	TAY
	RTS


MUL: 	STY	MATH1		;SAVE MULTIPLIER
	STX	MATH3		;SAVE MULTIPLICAND
	LDA	#0
	STA	MATH2		;ZERO HIGH RESULT
	LDX	#8		;THERE ARE 8 BITS TO TEST FOR

MUL10:	ASL	A		;SHIFT PRODUCT 1 TO DOUBLE IT.  FIRST LOOP=0
	ROL	MATH2		;AND MOVE BIT UP INTO RESULT HIGH BYTE

	ASL	MATH1		;SEE IF WE NEED TO ADD FOR THIS BIT
	BCC	MUL20
	CLC
	ADC	MATH3		;IF SO, ADD IN THE VALUE
	BCC	MUL20
	INC	MATH2		;IF CARRY, BRING UP TO HIGH RESULT
MUL20:	DEX
	BNE	MUL10
	TAX			;SAVE LOW BYTE IN RETURN REG	
	LDY	MATH2		;AND GET HIGH
	RTS


DIVIDE:	STA	MATH3		;PUT DIVISOR WHERE WE CAN SUBTRACT IT
	STX	MATH4		;SAVE COPY OF LOW DIVIDEND IN WORKING REG
	TYA			;GET HIGH	
	LDX	#8		;MAKE LOOP COUNT
D10:  	ASL	MATH4		;SHIFT UP LOW TO SEE IF WE CAN SUBTRACT
	ROL	A		;ROL THE BITS UP AND INTO THE CARRY
	BCS	D15		;IF CARRY, WE CAN ALWAYS SUBTRACT
	CMP	MATH3		;BUT SEE IF ITS BIG ENOUGH ON ITS OWN
	BCC	D20
D15:	SBC	MATH3
	INC	MATH4		;SHIFT IN A 1 BIT, WE DID SUBTRACT
D20:	DEX
	BNE	D10
	TAY			;PUT REMAINDER IN Y
	LDX	MATH4		;AND GET RESULT
	RTS


ADD_WORD:
	STX	MATH1
	CLC
	ADC	MATH1
	TAX
	BCC	AW10
	INY
AW10:	RTS


NEGATE:
	EOR	#H'FF
	CLC
	ADC	#1
	RTS


WRITE_SCNBUF:

	LDX	#0		;IF DATA, WRITE FROM BUFFER START
W20:	CPX	SCCNT
	BEQ	W90

	LDA	SCNBUF,X	;GET VERTICAL WRITE FLAG BYTE
	STA	H'2000
	INX
	LDA	SCNBUF,X	;GET HIGH ADDRESS
	STA	H'2006
	INX
	LDA	SCNBUF,X	;GET LOW
	STA	H'2006		;AND USE BOTH TO SET UP THE INDEX REG
	INX
	LDY	SCNBUF,X	;GET THE LENGTH TO WRITE OUT
	INX			;POINT TO THE DATA TO WRITE

W40:	LDA	SCNBUF,X
	INX
	STA	H'2007		;WRITE OUT A DATA BYTE
	DEY
	BNE	W40
	JMP	W20	

W90:	LDA	#0
	STA	SCCNT

STOP_NMI:			;CALL HERE TO DISABLE NMI

W100:	LDA	REG2000
	STA	H'2000		;REMOVE POSSIBLE VERTICAL WRITE BIT
 	RTS


VERT_WAIT:
	LDA	H'2002
	BPL	VERT_WAIT
	RTS

HIDESPRITES:
	LDA	#H'F8
	STA	STATSPR		;HIDE THE TOP OF SCREEN STATUS SPRITE
	LDA	#8		
	STA	STATSPR+2	;AND MARK AS IN USE

HIDEONLY:
	LDY	#0
	LDX	#63


HIDE2:

HS10:	LDA	#H'F8
	STA	SPRAM,Y		;MOVE OFF SCREEN
	LDA	#0		;AND FREE UP THE SPRITE, RESET PALETTE BITS
	STA	SPRAM+2,Y
HS11:	INY
	INY
	INY
	INY
	CPY	#252		;WRAP INDEX AT LAST SPRITE
	BEQ	HS11
	DEX
	BNE	HS10
	RTS




